面向对象编程
面向对象编程是很重要的编程思想,先简单介绍一下。
面向对象编程(object-oriented programming)简称OOP技术,是开发应用程序的一种新方法、新思想。过去的面向过程常常会导致所有的代码都包含在几个模块中,使程序难以阅读和维护。对软件修改时常常牵一动百,使以后的开发和维护难以为继,而使用OOP技术,常常需要使用许多代码模块,每个模块有自己的特定功能,它们是彼此独立的。这样就提高了代码重复使用的几率,更利于软件的开发、维护和升级。
在面向对象中,形象店来说,对象=(算法+数据结构),程序等于(对象+对象+对象+。。。。。。)
面向对象的三大特征:封装、继承、多态。
在介绍面向对象三大特征之前先引入类的概念:
类是对象概念在面向对象编程语言中的反映,是相同对象的集合。类描述了一系列在概念上有相同含义的对象,并为这些对象同意定义了编程语言上的属性和方法。
类是C#中功能最为强大的数据类型,像结构一样,类定义了数据类型的数据和行为。然后,开发者可以创建此类的实例的对象。类支持继承,而继承是面向对象编程的基础部分(注:C#中类只支持单继承)
类通过关键字class来声明:
1 类修饰符 class 类名 2 { 3 } 4 //声明一个简单的类 5 public class Car 6 { 7 public int number;//编号 8 public string color;//颜色 9 }
之前介绍了字段和属性,他们也是构成一个类的一部分。
构造函数和析构函数是类中比较特殊的两种成员函数。主要用来对对象进行初始化和回收对象资源,也就是说对象的生命周期从构造函数开始,以析构函数结束。
构造函数书是在创建给定类型的对象时执行的类方法,而且构造函数的名称必须和类的名称相同。写一个最简单的构造函数并调用它如下
class Program { private int x = 3; private int y = 4; private int z = 0; public Program() { z = x + y; } static void Main(string[] args) { Program pr = new Program(); Console.Write(pr.z); } }
构造函数可以有参数可以没有参数,没有参数的构造函数就是默认构造函数,不管在什么时候,只要用new关键字实例化对象,并且不为new提供任何参数,就会调用默认构造函数。
析构函数用~加类名命名。.NET Framwork类库有垃圾回收功能,当某个类的实例被认为不再有效,并符合析构条件。.NET Framework 类库的垃圾回收功能就会调用该类的析构函数实现垃圾回收。
注意:一个类中只能有一个析构函数,并且无法调用析构函数,它是被自动调用的,一个简单的析构函数如下
class Program { ~Program() //析构函数 { Console.Write("析构函数自动调用");//输出一个字符串 } static void Main(string[] args) { Program pr = new Program(); } }
对象的声明和实例化,这个很简单其实就是用new关键字进行实例化。实例化了一个对象,然后对对象进行操作。
注意:在没有对类进行实例化前,无法用类名调用类中的方法或字段。不实例化调用方法参考static。
说到这可能还对类和对象的概念很模糊:类和对象的区别就是,类是具有相同或相似结构、操作和约束规则的对象组成的集合;而对象是某一个具体化的实例,每一个类都使具有某些共同特征的对象的抽象。(类是一种抽象的数据类型,而对象是一个类的实例)
通俗点来讲一个类可以有很多个对象,用代码来说。
class Program { static void Main(string[] args) { Program pr = new Program();//pr是Program类的一个对象。 Program A = new Program();//A是Program类的另外一个对象。 } }
接下来说面向对象的三大特征:封装、继承和多态
封装:
C#中可以使用类来达到数据封装的效果,这样就可以把数据与方法封装成单一元素,以便于通过方法存取数据。除此之外还可以控制数据的存取方法。
设计类时,不希望那个直接存取类中的数据,而是希望通过方法存取数据,这样就可以达到封装的目地,方便维护升级,也可以在操作数据时多一层判断。
另外,封装还可以解决数据存取权限问题,我们并不希望我们的数据会被别人随便的修改,对于一些敏感数据,如果不加以限制让别人随便访问和修改,那么后果是很严重的。同样我们可以对外开放接口开放权限哪些可以访问那些不可以访问。封装的目地是增强安全性和简化编程。
class Myclass { private int x = 0; public int X { get { return x; } set { x = value; } } private int z = 0; public int Z { get { return z; } set { z = value; } } public int Add() { return x + z; } } class Program { static void Main(string[] args) { Myclass myadd = new Myclass(); myadd.X = 1; myadd.Z = 5; Console.Write(myadd.Add()); } }
类的继承
继承是面向对象编程最重要的特性之一。任何类都可以从另外一个类继承,这就是说,这个类拥有它继承类的所有成员。被继承的类叫做父类或基类,继承类的类叫做子类或者派生类,但是C#中只支持单继承。
继承一个类的时候,类成员的可访问性是一个重要的问题,子类不能访问父类的私有成员,但是可以访问父类的公共成员,意思就是只要使用public生命的类成员,就可以让一个类成员被基类和子类同时访问,同时也可被外部代码访问。
C#中提供了protect访问修饰符,只有子类能访问protect成员,父类和外部代码都不能访问protect成员。
除了成员的保护级别外,还可以为成员定义其继承行为。父类的成员可以是虚拟的,成员可以有继承它的类重写。子类可以提供成员的其它执行代码,这种执行代码不会删除原来的代码,仍可以在类中访问原来的代码,但外部代码不能访问它们。如果没有提供其他执行方式,外部代码就直接访问父类中成员的执行代码(绕口,自行理解。)
另外,基类还可以定义为抽象类。抽象类不可以直接实例化,要使用抽象类就必须继承这个类,然后再实例化。
class Myclass1 { private int x = 0; public int X { get { return x; } set { x = value; } } private int y = 0; public int Y { get { return y; } set { y = value; } } public int Add() { return x + y; } } class Myclass2:Myclass1//继承中间用冒号 { private int z = 0; public int Z { get { return z; } set { z = value; } } public int Add2() { return X + Y + Z; } } class Program { static void Main(string[] args) { Myclass1 myclass1 = new Myclass1(); Myclass2 myclass2 = new Myclass2(); myclass1.X = 1; myclass1.Y = 2; myclass2.X = 1; myclass2.Y = 2; myclass2.Z = 3; Console.Write(myclass1.Add()); Console.Write(myclass2.Add2()); } }
类的多态
多态使子类的实例化可以直接赋予基类的变量(这里不需要进行强制类型转换),然后直接就可以通过这个变量调用子类的方法。
在派生于同一个类的不同对象上执行任务时,多态是一种极为有效的技巧,,使用代码最少。可以把一组对象放到一个数组中然后调用他们的方法,在这种情况下多态的作用就体现出来,这些对象不必是相同类型的对象。当然如果它们继承自某个类,可以把这些子类都放到一个数组中。如果这些对象都有同名方法,就可以调用每个对象的同名方法。
class Myclass1 { private int x = 0; public int X { get { return x; } set { x = value; } } private int y = 0; public int Y { get { return y; } set { y = value; } } public virtual int Add() //定义一个virtual类型的方法以便于在子类中重写该方法求和 { return x + y; } } class Myclass2:Myclass1 { public override int Add() { int x = 1; int y = 2; return x + y; } } class Program { static void Main(string[] args) { Myclass2 myclass2 = new Myclass2();//实例化Myclass2的对象 Myclass1 myclass1 = (Myclass1)myclass2;//使用子类Myclass2的对象实例化基类Myclass1的对象 myclass1.X = 1; myclass2.Y = 2; Console.Write(myclass1.Add());//调用父类中的方法 Console.Write(myclass2.Add());//调用子类中的方法 } }
注意:
1、virtual修饰符不能同时与private、static、abstract或者override修饰符同时使用。
2、override修饰符不能与new、static或者virtual修饰符同时使用,并且重写方法只能用于重写父类中的虚方法。
3、C#中,继承、虚方法和重写方法组合在一起才能实现多态性。
参考资料:C#入门到精通