• C#面向对象编程及三大特性(二)


    1、继承关系实现多态:一种调用,多种实现。
        1)多态:隐藏基类 —new 则隐藏,隐藏看类型(来决定调用父类还是子类的方法):
    	  条件:父类子类写同名方法,子类方法名前加new(可以不加new)
          结果:对象的类型是子类则调用子类方法;是父类则调用父类方法
    	  
        2)多态:重写 —over重写,重写只管新(调用新重写的方法):
         条件1: 继承、里氏转换原则,且父类和子类有同名的方法
    		     在父类方法前加上virtual,在子类方法前加上override
         结果:  实现用父类对像调用子类方法
        3)隐藏基类应用:重写的子类调用自定义方法,不重写的继承父类方法,实现多态
    	  父类提供ToString方法,子类继承下来,可以直接调用ToString方法。
          不重写:如果子类,没有提供ToString方法,那么直接使用object提供的。
          重写:如果用户提供了ToString方法,那么调用时,就可以调用自定义的方法。
               (开放封闭原则:对扩展开放,对修改封闭。)
        4)重写方法实例:父类根据指向的子类不同,调用不同子类的方法,实现多态。
      
    View Code
    class Program
        {
            static void Main(string[] args)
            {
                Father f = null;
                Console.WriteLine("你要使用什么元件?(1、手机;2、灯)");
                switch (Console.ReadLine())
                {
                    case "1": f = new Phone("手机"); break;
                    case "2": f = new Light("Usb灯"); break;
                }
                f.Usb();
            }
        }
        class Father
        {
            string name;
             ---此处省略数行---
            public virtual void Usb()
            {
                Console.WriteLine("父类方法!");
            }
        }
        class Phone : Father
        {
            public Phone(string name) : base(name)
            { }
            public override void Usb()
            {
                Console.WriteLine("正在充电!");
            }
        }
        class Light : Father
        {
            public Light(string name) : base(name)
            { }
            public override void Usb()
            {
                Console.WriteLine("亮灯!");
            }
        }
    2、抽象类(难点)带有abstract的类
      抽象类是对一类事物或对象的抽象,统一了一类对象。
        ->抽象类当中的成员
    		->抽象成员:方法、属性(、索引、事件声明)
    		->非抽象成员,如Shape类中name
        ->抽象类的使用
    		->抽像类就是为了实现多态的,在使用多态的地方几乎都可以使用抽象
    		->抽象类是不能被实例化的,抽象类有构造方法(给非抽象成员赋初值)
       ->抽象成员的使用
    	(1)抽象方法的使用 
    			父类:[]abstract 返回类型 方法名() {}子类:[]override 返回类型 方法名() {}
    	(2)抽象属性的使用  快捷键Shift+Alt+F10
    	(3)抽象属性
    		-> 抽象与自动属性,本质不同
    			-> 自动属性,后台会有一个字段生成,体统会自动的添加对应的方法体
    			-> 抽象属性,因为没有方法体,所以get,set中什么都没有
    		-> 抽象与自动属性,结果不同
    			-> 自动属性,get,set必须共存
    			-> 抽象属性是可以有:只读、只写、可读可写之分的
    
    3、抽象方法实现多态(简单的说与继承关系父类使用多态相似)
    	不知道怎么实现;不需要实现,[public] abstract 返回类型 方法名( );	
       抽象方法必须在抽象类中,方法和类前面都有abstract
       抽象方法是为了实现多态,子类必须重写父类中的抽象方法
    	public override 父类提供的方法名(){}
       特例:如果子类也是抽象的,可以不重写父类分抽象方法
       实例:形状类(抽象父类),圆形、长方形、正方形三个子类,实现父类调用子类方法求周长和面积

      

    View Code
    namespace AbstractClass
        {
            class Program
            {
                static void Main(string[] args)
                {
                    while (true)
                    {
                        Shape[] s = { 
                                        new Circle("小圆",10),
                                        new Rectangle("小长",27.5,30),
                                        new Square("小方",100)
                                    };
                        for (int i = 0; i < s.Length; i++)
                        {
                            s[i].Introduction();
                            Console.WriteLine("我的面积是:{0}",s[i].Area());
                            Console.WriteLine("我的周长是:{0}",s[i].Perimeter()); 
                        }
                        Console.ReadKey();
                    }
                }
            }
        }
    
        abstract class Shape
        {
            //字段 属性
            string name;
    
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
    
            double pi = 3.14;
    
            public double Pi
            {
                get { return pi; }
                set { pi = value; }
            }
    
            //构造方法
            public Shape(string name)
            {
                this.name = name;
            }
            //抽象父类方法
            public abstract void Introduction();
            public abstract double Area();
            public abstract double Perimeter();
        }
        class Circle : Shape
        {
            //字段 属性 
            double r;
    
            public double R
            {
                get { return r; }
                set { r = value; }
            }
            
            //构造方法
            public Circle(string myname,double r1):base(myname)
            {
                r = r1;
            }
    
            //圆形子类方法
            public override void Introduction()
            {
                Console.WriteLine("我是一个圆:我叫{0}",Name);
            }
            public override double Area()
            {
                double area = 0;
                area = Pi * r * r;
                return area;
            }
            public override double Perimeter()
            {
                double perimeter;
                perimeter = 2 * Pi * r;
                return perimeter;
            }
        }
    
        
        class Rectangle : Shape
        {
            double length;
    
            public double Length
            {
                get { return length; }
                set { length = value; }
            }
            double width;
    
            public double Width
            {
                get { return width; }
                set { width = value; }
            }
    
            public Rectangle(string myname, double len,double wid)
                : base(myname)
            {
                length = len;
                width = wid;
            }
    
            public override void Introduction()
            {
                Console.WriteLine("我是矩形:{0}",Name);
            }
            public override double Area()
            {
                double area = 0;
                area = 2 * (length + width);
                return area;
            }
            public override double Perimeter()
            {
                double area = 0;
                area = length * width;
                return area;
            }
        }
        
        
        class Square : Shape
        {
            double a;
    
            public double A
            {
                get { return a; }
                set { a = value; }
            }
    
            public Square(string myname, double a1)
                : base(myname)
            {
                a = a1;
            }
    
            public override void Introduction()
            {
                Console.WriteLine("我是正方形:{0}",Name);
            }
            public override double Area()
            {
                double area = 0;
                area = 4 * a;
                return area;
            }
            public override double Perimeter()
            {
                double area = 0;
                area = a * a;
                return area;
            }
        }
    4.1、接口(与使用抽象类类似)
    接口是对能力和方法的抽象。
    		[public] interface 接口名
    		{
    			// 接口成员
    		}
    		-> 接口成员
    			-> 仅仅抽象能力,所以只有方法、属性、索引、事件声明
    			-> 接口中的成员就相当于抽象类中的抽象成员
    		-> 接口的定义和实现接口
    			-> 定义接口方法不用写访问修饰符,默认public
    			-> 子类继承自接口,实现接口中的方法时,写一个正常方法 (没有override)
    
    4.2、接口的多继承性(有同名方法的处理)
    (1)显式实现接口:
    	通过显式实现接口的方式为特定的接口重写特定的方法,调用方法时根据变量所属的接口类型来选择相应的方法。
    (2)调用接口:返回类型 接口名.方法名()显式实现的方法只能由接口调用
    	接口类的对象优先调用显式实现接口的方法,缺少的情况,再调用非显式实现的方法。
    	非接口类对象,只能调用非显式实现的方法,不能调用显式实现接口的方法。
    	示例:
        class Duck4 : Duck,IJiaoable1, IJiaoable2
        {
            public void Jiao()
            {
                Console.WriteLine("普通实现接口");
            }
            void IJiaoable1.Jiao()
            {
                Console.WriteLine("显式实现接口IDuck1");
            }
            void IJiaoable2.Jiao()
            {
                Console.WriteLine("显式实现接口IDuck2");
            }
        }
    	显式实现接口,Shift+Alt+F10生成,不加访问修饰符的(跟接口中一样)
    
    5、接口实现多态:鸭子的实例-联合使用继承和接口实现多态
    	不同鸭子游泳的方法不一样,所有鸭子都会游泳(继承)
    	不同鸭子叫的方法不一样,有的还不会叫(接口)

    View Code
        class Program
        {
            static void Main(string[] args)
            {
                Duck[] d = { new RealDuck(), new RubberDuck(),new WoodDuck()};
                for (int i = 0; i < d.Length; i++)
                {
                    d[i].Swim();
                    IJiaoable dk = d[i] as IJiaoable;
                    if (dk != null) 
                    {
                        dk.Jiao();
                    }                      
                }
                Console.ReadKey();
            }
        }
        abstract class Duck
        {
           public abstract void Swim();
        }
        interface IJiaoable
        {
            void Jiao();
        }
        class RealDuck : Duck, IJiaoable
        {
            public override void Swim()
            {
                Console.WriteLine("我是真的鸭子,我会游泳!我游啊游~~~");
            }
            public void Jiao()
            {
                Console.WriteLine("我是真的鸭子,嘎嘎嘎!");
            }
        }
        class RubberDuck : Duck, IJiaoable
        {
            public override void Swim()
            {
                Console.WriteLine("我是橡皮鸭子,我会游泳!我游啊游~~~");
            }
            public void Jiao()
            {
                Console.WriteLine("我是橡皮鸭子,唧唧~~唧唧~~");
            }
        }
        class WoodDuck : Duck  //没有叫的方法,于是不实现IJiaoable接口
        {
            public override void Swim()
            {
                Console.WriteLine("我是木头鸭子,我会游泳!我游啊游~~~");
            }
    }

    6.多接口中有同名方法的调用 根据对象的接口类型,优先调用显式实现的该接口方法。 没有针对该接口的显式实现方法可调用时,调用非显式实现的方法。 显式实现接口,Shift+Alt+F10生成,不加访问修饰符的(跟接口中一样)
    演示:普通实现接口和显示实现接口的调用
    执行结果: Duck1,普通实现接口 Duck1,普通实现接口 Duck2,显式实现接口IJiaoableA Duck2,普通实现接口 Duck3,普通实现接口 Duck3,显式实现接口IJiaoableB Duck4,显式实现接口IJiaoableA Duck4,显式实现接口IJiaoableB 代码清单:
    View Code
    namespace 显式实现接口演示
    {
        class Program
        {
            static void Main(string[] args)
            {
                    Duck[] dk = { new Duck1(), new Duck2(),new Duck3(),new Duck4() };
                    for (int i = 0; i < 4; i++)
                    {
                        IJiaoableA dka = dk[i] as IJiaoableA;
                        if (dka != null)
                            dka.Jiao();
    
                        IJiaoableB dkb = dk[i] as IJiaoableB;
                        if (dkb != null)
                            dkb.Jiao();
    
                        Console.WriteLine();
                    }
    
                    Console.ReadKey();
            }
        }
        
        public abstract class Duck
        {
        }
        interface IJiaoableA
        {
            void Jiao();
        }
    
        interface IJiaoableB
        {
            void Jiao();
        }
    
        //普通实现接口:不针对两个接口分别写方法
        class Duck1 : Duck, IJiaoableA, IJiaoableB
        {
            public void Jiao()
            {
                Console.WriteLine("Duck1,普通实现接口");
            }
        }
        //普通实现接口+显式实现接口“IDuck1”
        class Duck2 : Duck,IJiaoableA, IJiaoableB
        {
            public void Jiao()
            {
                Console.WriteLine("Duck2,普通实现接口");
            }
            void IJiaoableA.Jiao()
            {
                Console.WriteLine("Duck2,显式实现接口IJiaoableA");
            }
        }
        //普通实现接口+显式实现接口“IDuck2”
        class Duck3 : Duck,IJiaoableA, IJiaoableB
        {
            public void Jiao()
            {
                Console.WriteLine("Duck3,普通实现接口");
            }
            void IJiaoableB.Jiao()
            {
                Console.WriteLine("Duck3,显式实现接口IJiaoableB");
            }
        }
        //普通实现接口+显式实现接口“IDuck1”+显式实现接口“IDuck2”
        class Duck4 : Duck,IJiaoableA, IJiaoableB
        {
            public void Jiao()
            {
                Console.WriteLine("Duck4,普通实现接口");
            }
            void IJiaoableA.Jiao()
            {
                Console.WriteLine("Duck4,显式实现接口IJiaoableA");
            }
            void IJiaoableB.Jiao()
            {
                Console.WriteLine("Duck4,显式实现接口IJiaoableB");
            }
        }
    }
    7、多态的应用原则
    	多态实现方式:接口实现多态(对外)、抽象实现多态、父类实现多态(对内)
    	开发过程:    定义接口—定义抽象—父类—子类,最终使用的是子类,给用户的是接口。
    	              开发以抽象为主,能够抽象,尽量不要使用具体。
    	接口的使用原则:单一功能,组合使用。
    	抽象类是对一类事物的抽象,接口是对能力和方法的抽象。
    
    8、简单工厂设计模式(使项目模块化,可以将不同模块分给不同的项目小组去完成和维护)
       思路:在Main方法中使用父类变量接收工厂方法的子类对象,实现了“统一调用,不同实现”的多态性。
       步骤:写一个父类(抽象、具体、接口),定义统一的执行标准
       写若干个子类,分别重写父类方法或实现接口的方法
       写一个Factory类,根据需求new出子类,赋给父类变量返回
       Mian方法中完成需求输入,调用Factory类方法,得到对象调用特定子类的方法。
       
    演示:多态实现不同移动设备各自的读写操作 运行结果: 请选择您的设备类型: 输入编号或简码: 1.U盘(u/U), 2.Mp3(m/M), 3.移动硬盘(h/H) 1 U盘读数据中 U盘写数据中 请选择您的设备类型: 输入编号或简码: 1.U盘(u/U), 2.Mp3(m/M), 3.移动硬盘(h/H) 2 Mp3读数据中 Mp3写数据中 Mp3播放音乐中 请选择您的设备类型: 输入编号或简码: 1.U盘(u/U), 2.Mp3(m/M), 3.移动硬盘(h/H) 3 移动硬盘写数据中 移动硬盘读数据中 代码清单:
    View Code
    namespace IMoveMemableDemo
     {
        class Program
        {
            static void Main(string[] args)
            {
                while (true)
                {
                    //请用户插入移动设备
                    Console.WriteLine("请选择您的设备类型:\n输入编号或简码: 1.U盘(u/U), 2.Mp3(m/M), 3.移动硬盘(h/H)");
                    //根据用户输入调用“工厂模式”方法返回对象
                    IMoveMemable device = Factory.GetDevice(Console.ReadLine());
                    //使用设备 应用多态
                    if (device != null)
                    {
                        device.Read();
                        device.Write();
                        Mp3 mp3 = device as Mp3;
                        if (mp3!=null)
                            mp3.PlayMusic();
                    }
                    else
                    {
                        Console.WriteLine("您输入的设备类型不存在!");
                    }
                    Console.WriteLine();
                    Console.WriteLine();
                }
            }
        }
        
        public class Factory
        {
            public static IMoveMemable GetDevice(string name)
            {
                IMoveMemable device = null;
                switch (name)
                {
                    case "1":
                    case "u":
                    case "U": device = new UDisk(); break;
                    case "2":
                    case "m":
                    case "M": device = new Mp3(); break;
                    case "3":
                    case "h":
                    case "H": device = new MHardDisk(); break;
                    default:
                        break;
                }
                return device;
            }
        }
        
         public interface IMoveMemable
        {
            void Write();
            void Read();
        }
    
        public class UDisk : IMoveMemable
        {
            public void Write()
            {
                Console.WriteLine("U盘写数据中");
            }
    
            public void Read()
            {
                Console.WriteLine("U盘读数据中");
            }
        }
    
        public class Mp3 : IMoveMemable
        {
            public void Write()
            {
                Console.WriteLine("Mp3写数据中");
            }
    
            public void Read()
            {
                Console.WriteLine("Mp3读数据中");
            }
    
            public void PlayMusic()
            {
                Console.WriteLine("Mp3播放音乐中");
            }
        }
    
        public class MHardDisk : IMoveMemable
        {
            public void Write()
            {
                Console.WriteLine("移动硬盘读数据中");
            }
    
            public void Read()
            {
                Console.WriteLine("移动硬盘写数据中");
            }
        }
        
    }
    
    
  • 相关阅读:
    Linux systemctl 命令完全指南
    分享一些 Kafka 消费数据的小经验
    大数据日志采集系统
    使用Spring Boot Actuator将指标导出到InfluxDB和Prometheus
    这可能是最为详细的Docker入门吐血总结
    用不用lambda,这是一个问题
    es上的的Watcher示例
    Elasticsearch6.5.2 X-pack破解及安装教程
    oauth2.0通过JdbcClientDetailsService从数据库读取相应的配置
    Apache Beam实战指南 | 手把手教你玩转大数据存储HdfsIO
  • 原文地址:https://www.cnblogs.com/Extreme/p/3060968.html
Copyright © 2020-2023  润新知