zoukankan      html  css  js  c++  java
  • 面向对象---多态

    (一).多态概念

    让一个对象能够表现出多种状态(类型)

    (二).实现多态三种方法

    1.虚方法;2.抽象类;3.接口

     

    (三).虚方法(关键字virtual

    当父类的函数有实现时使用虚方法。使用虚方法意味着这个父类函数可以被子类重写,具体调用哪个被子类重新的函数,取决于父类对象装的是哪一个子类对象,但调用的始终是父类函数。

    作用:最大可能地取消各个子类对象中的差异性,减少代码冗余,增强程序的可读性。

    例子:

    员工类:

        class Employee
        {
            public virtual void clockOut()
            {
                Console.WriteLine("员工九点打卡");
            }
        }
        class Manager:Employee
        {
            public override void clockOut()
            {
                Console.WriteLine("经理十点打卡");
            }
        }
        class Programmer:Employee
        {
            public override void clockOut()
            {
                Console.WriteLine("程序猿不打卡");
            }
        }

    实现:

        class Program
        {
            static void Main(string[] args)
            {
                //员工九点打卡,经理十点打卡,程序猿不打卡
                Employee emp = new Employee();
                Manager mg = new Manager();
                Programmer pg = new Programmer();
                Employee[] emps = { emp, mg, pg };
                for (int i = 0; i < emps.Length; i++)
                {
                    emps[i].clockOut();
                }
                Console.ReadKey();
            }
        }

    结果:

    (四).抽象类(使用关键字abstract)

     当父类的方法不知道如何实现的时候,可以将父类写成抽象类,将方法写成抽象方法。

    注意:

    1.抽象类不允许创建对象。

    2.如果一个子类继承了一个抽象父类,那么它必须实现父类所有的抽象成员。

    3.抽象成员必须标记为abstract,并且不能有任何实现。

    4.抽象成员必须在抽象类中。抽象类可包含非抽象成员,并且抽象类中的实例成员可以不被子类发现。其中非抽象成员父类不可用,因为不能创建对象,但继承它的子类可以调用。

    5.子类继承抽象类后,必须把父类所有的抽象成员重写。但如果这个子类也是抽象类,那就不用重写。

    6.抽象成员的访问修饰符不能是private。

    7.子类重写父类方法时返回的签名,必须跟抽象父类抽象方法的签名一样。签名指的是方法的返回值和参数。

    例子:

    动物类:

    public abstract class Animals
        {
            //抽象类中可以有非抽象成员
            private int _age;    //年龄
            public int Age
            {
                get { return _age; }
                set { _age = value; }
            }
            public Animals(int age)
            {
                this.Age = age;
             }
            public abstract void Bark();  //动物叫的方式
        }
    
        public class Dog:Animals
        {
            public Dog(int age) : base(age)
            {
    
            }
    
            public override void Bark()  //重写父类函数
            {
                Console.WriteLine("小狗{0}岁了,会汪汪地叫~", this.Age);
            }
        }
        public class Cat : Animals
        {
            public Cat(int age) : base(age)
            {
    
            }
    
            public override void Bark()
            {
                Console.WriteLine("小猫{0}岁了,会喵喵地叫~", this.Age);
            }
        }
    

    实现:

        class Program
        {
            static void Main(string[] args)
            {
                //小狗汪汪叫,小猫喵喵叫
                Animals dog = new Dog(3);
                Animals cat = new Cat(3);
    
                dog.Bark();
                cat.Bark();
                Console.ReadKey();
            }
        }

    结果:

    虚方法和抽象类的区别:

    如果父类中的方法有默认的视线,并且父类需要被实例化时,可以将父类定义成一个普通类,用虚方法实现多态。

    如果父类中的方法没有默认实现,父类也不需要被实例化,则可以将该类定义为抽象类

    (五).序列化和反序列化

    序列化:将对象转化为二进制。

    反序列化:将二进制转化为对象。

    作用:以二进制的形式传输数据。

    要将一个类标记为被序列化的,在类的上方加上[Serializable]。

    例子:对一个文本的内容进行序列化和反序列化

    人类:

    namespace Serialization_And_Deserialization
    {
        [Serializable]
        public class Person
        {
            private string _name;    //名字
            
            public string Name
            {
                get { return _name; }
                set { _name = value; }
            }
    
            private char _gender;  //性别
    
            public char Gender
            {
                get { return _gender; }
                set { _gender = value; }
    
            }
    
            private int _age;  //年龄
    
            public int Age
            {
                get { return _age; }
                set { _age = value; }
            }
        }
    }

     实现:

        class Program
        {
            static void Main(string[] args)
            {
                Person p = new Person();
                p.Name = "chaara";
                p.Gender = '';
                p.Age = 12;
    
                //序列化,把文本文字(对象)转化为二进制存储在文本中
                using (FileStream fsWrite = new FileStream(@"C:UsersDesktop
    ew.txt", FileMode.OpenOrCreate, FileAccess.Write))
                {
                    BinaryFormatter bf = new BinaryFormatter();
                    bf.Serialize(fsWrite, p);
                }
                Console.WriteLine("序列化完毕!");
    
                //反序列化,把存储在文本的二进制转换成文字(对象)打印出来
                using (FileStream fsRead = new FileStream(@"C:UsersDesktop
    ew.txt", FileMode.Open, FileAccess.Read))
                {
                    BinaryFormatter bf = new BinaryFormatter();
                    p = (Person)bf.Deserialize(fsRead);
                    Console.WriteLine(p.Name);
                    Console.WriteLine(p.Gender);
                    Console.WriteLine(p.Age);
                    Console.ReadKey();
                }
            }
        }

    结果:

    序列化

    反序列化

    (六).接口(关键字interface)

    需要多继承时使用接口。接口就是一个规范、能力。接口命名一般为I...able。

    注意:

    1.接口的成员可以有:方法、属性、索引器、事件(本质上都是方法)。

    2.为了多态,接口不能被实例化。

    3.接口中的成员默认修饰符为public,不能有任何的实现。说白了就是光说不做,定义一组未实现的成员。

    4.接口与接口之间可以继承,并且可以多继承。

    5.实现接口的子类必须要实现该接口的全部成员。

    6.一个类如果同时继承了类和接口,类必须排在接口前面。

    7.显示实现接口是为了解决方法的重名问题。

    例子:

    接口:

    namespace Interface
    {
        public class Person : ISingingable
        {
            public void Singing()
            {
                Console.WriteLine("人在唱歌~");
            }
        }
        public interface IFlyable  //飞的能力
        {
            void Fly();  //接口中的成员不允许添加访问修饰符,默认为public;不允许有具体方法体的函数和字段(不存储数据),但有自动属性
        }
    
        public interface ISingingable  //唱歌的能力
        {
            void Singing();
        }
    
        public interface IDanceable  //唱歌的能力
        {
            void Dance();
        }
        public interface SuperIterface : ISingingable, IFlyable, IDanceable  //超级接口,实现接口与接口之间的多继承
        {
    
        }
    
        public class Bird : SuperIterface  
        {
            public void Fly()
            {
                Console.WriteLine("小鸟在飞翔~");
            }
    
            public void Dance()
            {
                Console.WriteLine("小鸟在跳舞~");
            }
    
    
            public void Singing()
            {
                Console.WriteLine("小鸟在唱歌~");
            }
        }
    }

     实现:

        class Program
        {
            static void Main(string[] args)
            {
                ISingingable s1 = new Person();  //创建子类对象赋值给接口
                SuperIterface s = new Bird();
                s1.Singing();
                s.Fly();
                s.Dance();
                s.Singing();
                Console.ReadKey();
            }
        }

    结果:

    练习:真的鸭子 、橡皮鸭子和木头鸭子游泳方式

    不同鸭子的接口

    namespace 接口练习
    {
        //真的鸭子会游泳  橡皮鸭子会游泳  木头鸭子不会游泳
    
        public interface ISwingingable
        {
            void Swinging();
        }
        public class RealDuck:ISwingingable
        {
            public void Swinging()
            {
                Console.WriteLine("真的鸭子靠翅膀脚丫子游泳");
            }
        }
    
        public class RubberDuck : ISwingingable
        {
            public void Swinging()
            {
                Console.WriteLine("橡皮鸭子飘在水中自由泳");
            }
        }
    
        public class WoodDuck : ISwingingable
        {
            public void Swinging()
            {
                Console.WriteLine("木头鸭子太重了游不动");
            }
        }
    }

    实现:

        class Program
        {
            static void Main(string[] args)
            {
                ISwingingable realDuck = new RealDuck(); //创建真鸭子对象
                ISwingingable rubberDuck = new RubberDuck();//创建橡皮鸭子对象
                ISwingingable woodDuck = new WoodDuck();  //创建木头鸭子对象
    
                realDuck.Swinging();
                rubberDuck.Swinging();
                woodDuck.Swinging();
                Console.ReadKey();
            }
        }

    结果:

    课后思考:

    什么时候用虚方法?

    什么时候用抽象类?

    什么时候用接口?

  • 相关阅读:
    分页查询
    matlab 常用机器学习算法的实现
    powerpoint(ppt) 的制作
    powerpoint(ppt) 的制作
    libsvm 的使用
    libsvm 的使用
    TFRecord —— tensorflow 下的统一数据存储格式
    numpy 数据类型与 Python 原生数据类型
    numpy 数据类型与 Python 原生数据类型
    Python str 与 bytes 类型(Python2/3 对 str 的处理)
  • 原文地址:https://www.cnblogs.com/chaara/p/7663222.html
Copyright © 2011-2022 走看看