【学习笔记】面向对象三大特性封装、继承和多态

一、封装

  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
原文地址:https://www.cnblogs.com/xyh9039/p/12593539.html