面向对象之封装

Posted 丢了蜡笔小新会哭〆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象之封装相关的知识,希望对你有一定的参考价值。

---恢复内容开始---

面向对象之封装

前言:在我们学习C#的过程中,尤其在学习面向对象的过程中,我们会依次的接触到面对对象的三大特征:封装 继承 多态。接下来我们会依次的进行分析,我们先来讲解封装。

在我们面向对象之前一直用的是面向过程的思维。那什么叫做面向过程呢:面向的是完成这件的事的过程,强调的是完成这件事的动作。

首先在这里请允许我先讲解一个例子:我想大家都看过赵本山演的一个小品,其中有一句非常经典的话:把大象放在冰箱里分几步(超幽默)?后来宋丹丹说了一句话:分三步,第一步:把冰箱门打开。第二部:把大象装进去。第三步:把冰箱门关上。

大家想想这个故事,这不就是一个典型的面向过程的思维吗。但是我们有没有想到过这个问题,当我们执行的人的不同的时候,是不是执行的过程也会改变呢。换句话说:如果我们用面向过程的思维开解决这件事的时候,当执行这件事的人的不同的时候,我们需要为不同的人量身定做不同的解决问题的方法。

比如说:张三来做这件事情,因为张三张的比较瘦小,个头也比较低,那他怎么来做这个事情呢?第一步:张三踩着板凳把冰箱门打开。第二步:张三找李四来帮忙来吧大象装进冰箱里。第三步:张三踩着板凳关闭冰箱门。

李四来做这件事情:因为李四张的比较健壮,它不需要别人来帮忙就能自己完成这件事。第一步:李四自己就能到冰箱门打开。第二步:李四自己就能把大象装进冰箱里。第三步:李四自己就能把冰箱门关上。

通过张三和李四因为他们自身的原因,就需要为他们两个制作不同的解决问题的方法。

ok,

那我们如何来解决这个问题呢,这就引出了我们面向对象的方式(也是一种编程的思维),我们可以简单的理解面向对象为:找个对象帮你做事,我们就拿“把大象装进冰箱里”这件事情来说,我们可以把大象或者冰箱当作对象。这时候我们可以把冰箱当作做对象:第一步:冰箱门可以被打开。第二步:大象可以被装进冰箱里。第三步:冰箱门可以被关闭。

这时候我们用面向对象的方式就可以屏蔽各个对象之间的差异(人),我们就把“冰箱门可以被打开”这个封装为一个方法,我们外面不需要知道里面是如何编写的,只需知道我们调用这个方法就可以把冰箱门打开,屏蔽各个对象之间的差异,意在写出一个通用的代码。

然而对于我们程序员而言:万物皆对象。

接下来我们在日常的生活中描述一个人的特征和行为:

特征:

    姓名:性别:身高: 体重: 年龄:

 行为:

   吃喝拉撒睡一切正常。

 然而我们在代码中描述一个对象的时候, 通过描述这个对象的属性(特征)和方法(行为),对象必须是看得见摸得着的。

我们把这些具有相同属性和相同方法的对象进行进一步的封装,抽象出来一个类这个概念。

类就是个模子,确定了对象应该有的属性和方法,对象是根据类创建出来的。

类就是一个盖大楼的图纸,对象就是盖出来的大楼。

类的语法:

[Publicclass 类名

{

      字段,

      属性,

      方法,

} 

当我们写好一个类的时候。,我们需要创建这个类的对象,那么我们管创建这个类的对象的过程称之为类的实例化。使用关键字 new  。

this 表示当前类的对象。类是不占内存的,而对象是占内存的。 

属性的定义

属性的作用就是保护字段,对字段的取值和赋值进行限定。

属性的本质就是两个方法,一个叫get(),一个叫set();

首先我们先看一个Person类,代码如下:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _01面向对象
{
    public class Person
    {
        //名字
        private string _name;
        public string Name
        {
            //当你输出属性的值得时候 会执行get方法
            get { return _name; }
            //当你给属性赋值的时候 首先会执行set方法
            set { _name = value; }
        }
        //年龄
        private int _age;
        public int Age
        {
            get { return _age; }
            set
            {

                if (value < 0 || value > 100)
                {
                    value = 0;
                }

                _age = value;
            }
        }
        //性别
        private char _gender;
        public char Gender
        {
            get
            {
                if (_gender != \'\' && _gender != \'\')
                {
                    return _gender = \'\';
                }
                return _gender;

            }
            set { _gender = value; }
        }
        //方法
        public void CHLSS()
        {
            Console.WriteLine("我叫{0},我今年{1}岁了,我是{2}生,我可以吃喝拉撒睡哟~~~", this.Name, this.Age, this.Gender);
        }
    }
}

 


首先我们说get(),set()本质上就是两个方法,这时候我们通过反编译工具可以看到.其实set()方法的本质代码如下:

public void set_Name(string value)
{
    this._name=value;
}

而get()方法的本质是:

public string get_Name()
{
    return this._name;
}

那么我们怎么解释属性这个概念呢?对于我们编程来说,数据对于我们来说是非常重要的,然而我们字段是存储数据的。那么这么来说属性就是用来保护字段的。

字段就是女人(在家相夫教子),而属性就是男人(在外面给别人打交道)。

我们无论在任何的时候都不应该让别的类轻易的访问到我们的字段,所以当外界进行访问数据的时候,不应该直接访问我们的数据,而是访问属性。

构造函数

作用:帮助我们初始化对象(给对象的每个属性依次赋值)。                    

(1):构造函数没有返回值,连Void也没有。

(2):构造函数的名称必须跟类名一样。

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _04面向对象练习
{
    public class Student
    {
        //字段、属性、方法、构造函数
       //析构函数  构造函数
        //当程序结束的时候  析构函数才执行
        //帮助我们释放资源
        //GC Garbage Collection
        ~Student()
        {
            Console.WriteLine("我是析构函数");
        }

        public Student(string name, int age, char gender, int chinese, int math, int english)
        {
            this.Name = name;
            this.Age = age;
            this.Gender = gender;
            this.Chinese = chinese;
            this.Math = math;
            this.English = english;
        }
        public Student(string name, int chinese, int math, int english):this(name,0,\'c\',chinese,math,english)
        {
            //this.Name = name;
            //this.Chinese = chinese;
            //this.Math = math;
            //this.English = english;
        }
        public Student(string name, int age, char gender)
        {
            this.Name = name;
            if (age < 0 || age > 100)
            {
                age = 0;
            }
            this.Age = age;
            this.Gender = gender;
        }

        public Student()
        { 
            
        }

        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        private int _age;
        public int Age
        {
            get { return _age; }
            set
            {
                if (value < 0 || value > 100)
                {
                    value = 0;
                }
                _age = value;
            }
        }
        private char _gender;
        public char Gender
        {
            get
            {
                if (_gender != \'\' && _gender != \'\')
                {
                    return _gender = \'\';
                }
                return _gender;
            }
            set { _gender = value; }
        }
        private int _chinese;
        public int Chinese
        {
            get { return _chinese; }
            set { _chinese = value; }
        }
        private int _math;
        public int Math
        {
            get { return _math; }
            set { _math = value; }
        }
        private int _english;
        public int English
        {
            get { return _english; }
            set { _english = value; }
        }

        /// <summary>
        /// 打招呼的方式
        /// </summary>
        public void SayHello()
        {
            Console.WriteLine("我叫{0},我几年{1}岁了,我是{2}生", this.Name, this.Age, this.Gender);
        }

        /// <summary>
        /// 显示分数的方式
        /// </summary>
        public void ShowScore()
        {
            Console.WriteLine("我叫{0},我的总成绩是{1},平均成绩是{2}", this.Name, this.Chinese + this.Math + this.English, (this.Chinese + this.Math + this.English) / 3);
        }

    }
}

 


现在我们总结一下new关键字帮助我们做了什么事情?

1.在内存的堆中开辟了一块空间。

2.在开辟的空间中创建对象。

3.调用对象的构造函数进行初始化赋值的操作。

this关键字的作用?

1.代表当前类的对象

2.在类当中显示的调用本类的构造函数。

 

 

静态和非静态的区别:

1.在非静态中,既可以有实例成员,也可以有静态成员。

2.在调用非静态成员时,需要使用对象名.实例成员名。

   在调用静态成员的时候,需要使用类名.静态成员名。

 总结:静态成员必须使用类名去调用,而实例成员使用对象名调用。

            静态函数中,只能访问静态成员,不允许访问实例成员。

            实例函数中,既可以使用静态成员,也可以使用实例成员。

            静态类中值允许有静态的成员,不允许有实例的成员。

所以你要想你的类当作为一个“工具类“使用的话,这时候可以考虑将成静态的。

静态类在整个项目中资源共享。

只有在程序全部结束之后,静态类才会释放资源。

下面我们来做到题:写一个Ticket类,有一个距离的属性(本属性是只读的,在构造函数中进行赋值的操作),不能是负数,有一个价格的属性,价格属性只读,并且要根据distance计算价格Price(1元/公里):0-100公里    票折不打折          101-200    打9.5折      201-300   打9折      300以上公里  打8折

1.距离属性是只读的:

//距离
        private double _distance;
        /// <summary>
        /// 距离属性是只读的
        /// </summary>
        public double Distance
        {
            get { return _distance; }
        }

2.在类的构造函数中对距离进行赋值的操作:

         /// <summary>
        /// 在构造函数中进行赋值的操作
        /// </summary>
        /// <param name="distance">距离</param>
        public Ticket(double distance)
        {
            //如果距离为的数值为负数的话  距离就直接等于零
            if (distance < 0)
            {
                distance = 0;
            }
            this._distance = distance;
        }

3.价格的属性(只读,按照公里数对价格进行计算):

          private double _price;
          //0-100公里        票价不打折
        //101-200公里    总额打9.5折
        //201-300公里    总额打9折
        //300公里以上    总额打8折
        public double Price
        {
            get
            {
                if (_distance > 0 && _distance <= 100)
                {
                    return _distance * 1.0;
                }
                else if (_distance >= 101 && _distance < 200)
                {
                    return _distance * 0.95;
                }
                else if (_distance >= 201 && _distance < 300)
                {
                    return _distance * 0.9;
                }
                else
                {
                    return _distance * 0.8;
                }
            }
        }
        /// <summary>
        /// 显示票价的方法
      /// </summary>
        public void ShowTicket()
        {
            Console.WriteLine("{0}公里需要{1}元",Distance,Price);
        }

Main方法的调用的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _05练习
{
    class Program
    {
        static void Main(string[] args)
        {
            //创建类的对象
            Ticket t = new Ticket(150);
            //方法的调用,显示公里数和价格
            t.ShowTicket();
            Console.ReadKey();
        }
    }
}

 

本次就介绍到这里,希望大家多提意见,谢谢。

---恢复内容结束---

以上是关于面向对象之封装的主要内容,如果未能解决你的问题,请参考以下文章

Python面向对象之:三大特性:继承,封装,多态。

19.Python面向对象之:三大特性:继承,封装,多态。

面向对象之:三大特性:继承(已讲),封装,多态

Java面向对象之封装

python之路之前没搞明白4面向对象(封装)

面向对象之:封装,多态,以及类的约束