面向对象之封装
Posted 丢了蜡笔小新会哭〆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象之封装相关的知识,希望对你有一定的参考价值。
---恢复内容开始---
面向对象之封装
前言:在我们学习C#的过程中,尤其在学习面向对象的过程中,我们会依次的接触到面对对象的三大特征:封装 继承 多态。接下来我们会依次的进行分析,我们先来讲解封装。
在我们面向对象之前一直用的是面向过程的思维。那什么叫做面向过程呢:面向的是完成这件的事的过程,强调的是完成这件事的动作。
首先在这里请允许我先讲解一个例子:我想大家都看过赵本山演的一个小品,其中有一句非常经典的话:把大象放在冰箱里分几步(超幽默)?后来宋丹丹说了一句话:分三步,第一步:把冰箱门打开。第二部:把大象装进去。第三步:把冰箱门关上。
大家想想这个故事,这不就是一个典型的面向过程的思维吗。但是我们有没有想到过这个问题,当我们执行的人的不同的时候,是不是执行的过程也会改变呢。换句话说:如果我们用面向过程的思维开解决这件事的时候,当执行这件事的人的不同的时候,我们需要为不同的人量身定做不同的解决问题的方法。
比如说:张三来做这件事情,因为张三张的比较瘦小,个头也比较低,那他怎么来做这个事情呢?第一步:张三踩着板凳把冰箱门打开。第二步:张三找李四来帮忙来吧大象装进冰箱里。第三步:张三踩着板凳关闭冰箱门。
李四来做这件事情:因为李四张的比较健壮,它不需要别人来帮忙就能自己完成这件事。第一步:李四自己就能到冰箱门打开。第二步:李四自己就能把大象装进冰箱里。第三步:李四自己就能把冰箱门关上。
通过张三和李四因为他们自身的原因,就需要为他们两个制作不同的解决问题的方法。
ok,
那我们如何来解决这个问题呢,这就引出了我们面向对象的方式(也是一种编程的思维),我们可以简单的理解面向对象为:找个对象帮你做事,我们就拿“把大象装进冰箱里”这件事情来说,我们可以把大象或者冰箱当作对象。这时候我们可以把冰箱当作做对象:第一步:冰箱门可以被打开。第二步:大象可以被装进冰箱里。第三步:冰箱门可以被关闭。
这时候我们用面向对象的方式就可以屏蔽各个对象之间的差异(人),我们就把“冰箱门可以被打开”这个封装为一个方法,我们外面不需要知道里面是如何编写的,只需知道我们调用这个方法就可以把冰箱门打开,屏蔽各个对象之间的差异,意在写出一个通用的代码。
然而对于我们程序员而言:万物皆对象。
接下来我们在日常的生活中描述一个人的特征和行为:
特征:
姓名:性别:身高: 体重: 年龄:
行为:
吃喝拉撒睡一切正常。
然而我们在代码中描述一个对象的时候, 通过描述这个对象的属性(特征)和方法(行为),对象必须是看得见摸得着的。
我们把这些具有相同属性和相同方法的对象进行进一步的封装,抽象出来一个类这个概念。
类就是个模子,确定了对象应该有的属性和方法,对象是根据类创建出来的。
类就是一个盖大楼的图纸,对象就是盖出来的大楼。
类的语法:
[Public] class 类名
{
字段,
属性,
方法,
}
当我们写好一个类的时候。,我们需要创建这个类的对象,那么我们管创建这个类的对象的过程称之为类的实例化。使用关键字 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(); } } }
本次就介绍到这里,希望大家多提意见,谢谢。
---恢复内容结束---
以上是关于面向对象之封装的主要内容,如果未能解决你的问题,请参考以下文章