一、封装
1、隔离,外部不用关心怎么实现,只要接口不变,内部可以随意扩展。
2、数据安全 private protected 数据结构,只能通过公开方法来访问,而不是随便改。
3、降低耦合 提高重用性 尽量隐藏更多的东西。
二、继承
1、子类拥有父类的一切属性和行为,代码重用。
2、单继承,也就是只有一个父类。
三、多态
1、一个类可以用做多个类型,就是多态,当然还有方法。
2、编译时多态、运行时多态、接口多态、继承多态。
接下来我们来看个Demo,首先我们准备一些测试类
using System; namespace MyOO { /// <summary> /// 面向对象测试类 /// </summary> public class OOTest : IFlyable, ISwimable { /// <summary> /// 实现IFlyable接口 /// </summary> public void Fly() { Console.WriteLine("OOTest Fly"); } /// <summary> /// 显示实现ISwimable接口,用于解决方法的重名问题 /// </summary> void ISwimable.Swin() { Console.WriteLine("OOTest Swin"); } /// <summary> /// OOTest自己的Swin方法 /// </summary> public void Swin() { Console.WriteLine("我是OOTest自己的Swin方法"); } } /// <summary> /// 飞接口 /// </summary> public interface IFlyable { /// <summary> /// 飞 /// </summary> void Fly(); } /// <summary> /// 游泳接口 /// </summary> public interface ISwimable { /// <summary> /// 游泳 /// </summary> void Swin(); } /// <summary> /// 父类(抽象类) /// </summary> public abstract class ParentClass { /// <summary> /// 构造函数 /// </summary> public ParentClass(int id) { } /// <summary> /// 普通方法 /// </summary> public void CommonMethod() { Console.WriteLine("ParentClass CommonMethod"); } /// <summary> /// virtual 虚方法 必须包含实现 但是可以被重载 /// </summary> public virtual void VirtualMethod() { Console.WriteLine("ParentClass VirtualMethod"); } /// <summary> /// 虚方法重载 /// </summary> /// <param name="name"></param> public virtual void VirtualMethod(string name) { Console.WriteLine("ParentClass VirtualMethod"); } /// <summary> /// 抽象方法(必须放在抽象类中) /// </summary> public abstract void AbstractMethod(); } /// <summary> /// 子类 /// </summary> public class ChildClass : ParentClass { /// <summary> /// 实例化子类的时候,是先完成父类的实例化的 /// </summary> public ChildClass() : base(1)//调用父类的构造函数 { } /// <summary> /// new 隐藏 /// </summary> public new void CommonMethod() { Console.WriteLine("ChildClass CommonMethod"); } /// <summary> /// 普通方法重载一 /// </summary> /// <param name="name"></param> public void CommonMethod(string name) { Console.WriteLine("ChildClass CommonMethod OverLoad1"); } /// <summary> /// 普通方法重载二 /// </summary> public void CommonMethod(string name, int id) { Console.WriteLine("ChildClass CommonMethod OverLoad2"); } /// <summary> /// virtual 可以被覆写 /// </summary> /// <param name="obj"></param> /// <returns></returns> public override void VirtualMethod() { Console.WriteLine("ChildClass VirtualMethod"); base.VirtualMethod();//base表示调用直接父类的这个方法 } /// <summary> /// 抽象方法必须覆写(标记为sealed密封方法则不允许子类再去重写它) /// </summary> public sealed override void AbstractMethod() { Console.WriteLine("ChildClass AbstractMethod"); } } /// <summary> /// 派生类 /// </summary> public class GrandClass : ChildClass { //这是错误的,密封的,无法进行重写 //public override void AbstractMethod() //{ // base.AbstractMethod(); //} /// <summary> /// 重写虚方法 /// </summary> public override void VirtualMethod() { base.VirtualMethod(); } } }
然后来看下具体使用
using System; namespace MyOO { /// <summary> /// 小结: /// 使用父类声明接收子类对象 /// 实现多态的几种方式:方法的隐藏、方法的重载、虚方法、抽象方法、接口 /// 1、方法的隐藏 /// 使用new关键字,这是个普通方法,普通方法调用是由编译时决定,调用的是父类的方法还是子类的方法取决于它的声明类型 /// /// 2、方法的重载 /// 这是编译时多态,方法的调用是由编译时决定的 /// /// 3、虚方法 /// 用virtual关键字,子类可以用override去重写它,这是运行时多态,如果子类有去实现父类的虚方法则调用子类的方法,否则调用父类的方法 /// /// 4、抽象方法 /// 用abstract关键字,子类需要用override关键字去覆写它,这是运行时多态,调用子类的方法 /// 含有抽象方法的类一定是抽象类,抽象类不能被实例化,抽象类中可以有抽象成员也可以有非抽象成员 /// /// 4、接口 /// 用interface关键字,子类去实现接口成员不需要用override关键字,这是运行时多态,调用子类的方法 /// 接口不能被实例化,接口成员不允许添加访问修饰符,默认是public /// 接口成员必须是函数成员(本质都是方法),并且都是抽象成员不能有任何的实现,不能有常量和字段 /// 接口成员包括方法、属性、索引器、事件,不能有字段和构造函数 /// 接口可以继承多个接口 /// 显示实现接口的目的是为了解决方法的重名问题 /// </summary> class Program { static void Main(string[] args) { //使用父类声明接收子类对象 ParentClass parent = new ChildClass(); //方法的隐藏 Console.WriteLine("下面是parent.CommonMethod()"); parent.CommonMethod();//子类new隐藏 父类方法 普通方法由编译时决定--提高效率 Console.WriteLine(); //换行 //虚方法 Console.WriteLine("下面是parent.VirtualMethod()"); parent.VirtualMethod();//子类覆写的虚方法 子类方法 虚方法由运行时决定的--多态灵活 Console.WriteLine(); //换行 //抽象方法 Console.WriteLine("下面是parent.AbstractMethod()"); parent.AbstractMethod();//子类实现的抽象方法 子类方法 抽象方法由运行时决定的--多态灵活 Console.WriteLine(); //换行 //接口 Console.WriteLine("下面是fly.Fly()"); IFlyable fly = new OOTest(); fly.Fly();//子类实现的抽象方法 子类方法 抽象方法由运行时决定的--多态灵活 Console.WriteLine(); //换行 Console.WriteLine("下面是swim.Swin()"); ISwimable swim = new OOTest(); swim.Swin();//子类实现的抽象方法 子类方法 抽象方法由运行时决定的--多态灵活 Console.WriteLine(); //换行 Console.WriteLine("下面是test.Swin()"); OOTest test = new OOTest(); test.Swin();//OOTest自己的Swin方法 Console.ReadKey(); } } }
最后我们来总结下多态的情况:
1、编译时多态:方法的重载,这个就不必多说了。
2、运行时多态:虚方法、抽象类、接口
1)什么时候用虚方法来实现多态?
可以抽象出一个父类,并且父类中可以写出这几个子类共有的方法,且知道具体实现方式,且还需要创建父类对象。
2)什么时候用抽象类来实现多态?
可以抽象出一个父类,并且父类中可以写出这几个子类共有的方法,但又不知道如何具体实现这些方法。
3)什么时候用接口来实现多态?
在几个类中根本找不出父类,但它们具有共同的行为、共同的能力。
Demo源码:
链接:https://pan.baidu.com/s/1-PWuGw5Yw3D_bSWuCDk26w 提取码:z9gh