zoukankan      html  css  js  c++  java
  • 多态的使用 虚方法、抽象类、接口

    1、新建一个person类

    public class Person
        {
            public string Name;
            
            public Person(string name)
            {
                this.Name = name;
            }
            public void SayHello()
            {
                Console.WriteLine($@"我是人,是叫{Name}");
            }
        }

    2、新建几个person的子类

    public class Chinese : Person
        {
            public Chinese(string name) : base(name)
            { }
            public void SayHello()
            {
                Console.WriteLine("我是中国人,我叫{0}", this.Name);
            }
        }
        public class Japanese : Person
        {
            public Japanese(string name) : base(name)
            { }
            public void SayHello()
            {
                Console.WriteLine("我是日本人,我叫{0}", this.Name);
            }
        }
        public class Korea : Person
        {
            public Korea(string name) : base(name)
            { }
            public void SayHello()
            {
                Console.WriteLine("我是韩国人,我叫{0}", this.Name);
            }
        }
        public class American : Person
        {
            public American(string name) : base(name)
            { }
            public void SayHello()
            {
                Console.WriteLine("我是美国人,我叫{0}", this.Name);
            }
        }

    3、这时候,创建几个不同的对象,把内容给展示出来

            static void Main(string[] args)
            {
                //多态:让一个对象能够表现出多种的状态(类型)
                
                Chinese cn1 = new Chinese( "李雷");
                Chinese cn2 = new Chinese("韩梅梅");
                Japanese j1 = new Japanese("松下幸之助");
                Korea k1 = new Korea("金秀贤");
                American a1 = new American("科比");
                American a2 = new American("奥尼尔");
                List<Person> list = new List<Person>() {cn1,cn2,j1,k1,a1,a2 };
                foreach (Person p in list)
                {
                    p.SayHello();
                }
                Console.ReadKey();
            }

    4、那么问题来了,这里每个对象调用的都是父类的方法,没有调用自己类的方法,如果我希望调用的是自己的方法,那该怎么办呢?

    foreach (Person p in list)
                {
                    if (p is Chinese)
                    {
                        Chinese cn = (Chinese)p;
                        cn.SayHello();
                    }
                    else if(p is Korea)
                    {
                        Korea ko = (Korea)p;
                        ko.SayHello();
                    }
                    else if (p is Japanese)
                    {
                        Japanese jp = (Japanese)p;
                        jp.SayHello();
                    }
                    else if (p is American)
                    {
                        American am = (American)p;
                        am.SayHello();
                    }
                }
                Console.ReadKey();

    5、这里使用了if  else 进行类型判断后转换的方法。除此之外还有没有别的方法呢?有三种方法:A、虚方法   B、抽象类    C、接口

    A、将父类的方法标记为虚方法,使用virtual,在子类的方法前面加override

        public class Person
        {
            public string Name;
            
            public Person(string name)
            {
                this.Name = name;
            }
            public virtual void SayHello()
            {
                Console.WriteLine($@"我是人,是叫{Name}");
            }
        }
        public class Chinese : Person
        {
            public Chinese(string name) : base(name)
            { }
            public override void SayHello()
            {
                Console.WriteLine("我是中国人,我叫{0}", this.Name);
            }
        }
        public class Japanese : Person
        {
            public Japanese(string name) : base(name)
            { }
            public override void SayHello()
            {
                Console.WriteLine("我是日本人,我叫{0}", this.Name);
            }
        }
        public class Korea : Person
        {
            public Korea(string name) : base(name)
            { }
            public override void SayHello()
            {
                Console.WriteLine("我是韩国人,我叫{0}", this.Name);
            }
        }
        public class American : Person
        {
            public American(string name) : base(name)
            { }
            public override void SayHello()
            {
                Console.WriteLine("我是美国人,我叫{0}", this.Name);
            }
        }

    说明:调用了父类的sayHello,然而这个list中装的是子类的对象,于是就用子类的方法。如果这时存入的是Person的对象,依然会使用Person的方法。

    B、用抽象类实现。抽象类中,写抽象方法。抽象方法是没有方法体的(即,没有大括号)。这个方法是没法运行的,他的存在意义就是让子类来实现它。

    class Program
        {
            static void Main(string[] args)
            {
                Chinese cn1 = new Chinese( "李雷");
                Chinese cn2 = new Chinese("韩梅梅");
                Japanese j1 = new Japanese("松下幸之助");
                Korea k1 = new Korea("金秀贤");
                American a1 = new American("科比");
                American a2 = new American("奥尼尔");
                //Person p1 = new Person("Aman");
                List<Person> list = new List<Person>() { cn1, cn2, j1, k1, a1, a2 };// ,p1};
                foreach (Person p in list)
                {
                    p.SayHello();
                }
                Console.ReadKey();
            }
    
        }
    
    public abstract class Person
        {
            public string Name;
            
            public Person(string name)
            {
                this.Name = name;
            }
            public abstract void SayHello();//抽象方法  
         //{}
    }

    注意这里的区别,如果是A虚方法,那么他自己也是可以运行的,如果是抽象的,就没法创建对象了。(接口也不能创建对象)

    C、接口

    接口是一种规范,也是一种能力。以 I 开头 ,以able结尾 如  IFlyable。

    接口中不需要访问修饰符,都是public的。

    接口中不能写具有方法体的函数,光说不做,只是定义了一组未实现的成员。

    接口中不能有字段。(但是可以有  string Name {get;set;} 这样的自动属性。其实这也是方法)

     接口和接口之间可以结成,并且可以多继承。

    接口并不能用去继承一个类。实现接口的类,必须实现所有的接口。

    interface ISayHelloable
        {
            string Name { get; set; }
            void SayHello();
        }
    
        public class Chinese: ISayHelloable
        {
            public Chinese(string inputName)
            {
                Name = inputName;
            }
    
            string chineseName;
            public string Name
            {
                get{return chineseName ; }
                set{ chineseName = value;}
            }
    
            public void SayHello()
            {
                Console.WriteLine($@"我是中国人,我的中国名字叫{Name}");
            }
        }
        public class American : ISayHelloable
        {
            public American(string inputName)
            {
                Name = inputName;
            }
            string AmericanName;
            public string Name
            {
                get { return AmericanName; }
                set { AmericanName = value; }
            }
            public void SayHello()
            {
                Console.WriteLine($@"我是美国人,我的美国名字叫{Name}");
            }
        }

    首先定义一个接口,并用两个类去实现这个接口。

    再创建两个不同的类对象,因为他们都实现了这个接口,于是定义一个List把他们装进来。

    然后用接口的方法来分别调用各自的方法。

    static void Main(string[] args)
            {
                List<ISayHelloable> persons = new List<ISayHelloable>();
                persons.Add(new Chinese("李磊"));
                persons.Add(new American("Adam"));
                persons.Add(new Chinese("韩梅梅"));
                persons.Add(new American("John"));
                foreach (ISayHelloable p in persons)
                {
                    p.SayHello();
                }
                Console.ReadKey();
    
            }

     综上:

    1、构建“主从”这种关系的类时,使用虚方法。

    2、构建“父子”这种关系的类时,使用抽象。

    3、在哪里都可以用接口。

    接口的优势:A、多继承。B、相互之间无关的类实现你的接口。C、想指定一个特定数据类型的行为,但是不用去关心由谁来实现这一行为。

    说的不全面,暂且这么记,以后对这个问题认识深刻后,再来修改。

  • 相关阅读:
    Web学习之css
    Spring学习之第一个hello world程序
    MySQL基础学习总结
    Jmeter参数化
    mysql慢查询解析-linux命令
    mysql慢查询
    mysql_存储引擎层-innodb buffer pool
    mysql_Qcahce
    memocached基础操作
    Memcached安装配置
  • 原文地址:https://www.cnblogs.com/adamgq/p/8387088.html
Copyright © 2011-2022 走看看