zoukankan      html  css  js  c++  java
  • 黑马程序员--多态

    ---------------------- ASP.Net+Android+IOS开发 .Net培训期待与您交流! ----------------------

    ■子类可以有与父类方法名相同的方法

      ♢签名不同(重载)

      ♢签名相同(隐藏基类方法)

    ■子类可以重写父类方法

      ♢虚方法

      ♢重写方法

      ♢重写基类方法一样可以调用基类方法

    ■多态就是对象可以表现多个类型的能力.(一种表现形式,实现多种功能)

    ■几种建立多态的方式

      ♢用父类实现多态

      ♢用抽象类实现多态

      ♢用接口实现多态

    ■多态版本控制

      ♢需要保留基类方法使用new关键字

      ♢需要重写方法使用override关键字

    1.隐藏基类方法

        class Program
        {
            static void Main(string[] args)
            {
                Base b = new Base();
                b.Func();//结果:我是一个父类
                Sub s = new Sub();
                s.Func();//结果:我是一个子类,此处隐藏了基类的方法
                Base b1 = s;
                b1.Func();//结果:我是一个父类
                Console.ReadKey();
            }
        }
        class Base
        {
            public void Func()
            {
                Console.WriteLine("我是一个父类");
            }
        }
        class Sub : Base
        {
            public new void Func()//此处可以直接写成 public void Func()省略掉new,我们姑且称为隐式隐藏
            {
                Console.WriteLine("我是一个子类");
            }
        }

    通过上述例子,我们得知:隐藏基类方法时,我们访问到的方法是依据引用变量的,引用变量是基类访问到的就是基类的方法,引用变量是子类,访问到的是子类的方法

    2.重写基类方法

    class Program
        {
            static void Main(string[] args)
            {
               //重写基类方法:在基类方法前面加上virtual,在子类方法前加上override
                Base b = new Base();
                b.Func();//结果:我是一个父类
                Sub s = new Sub();
                s.Func();//结果:我是一个子类,重写
                Base b1 = s;
                b1.Func();//结果:我是一个子类,重写
                Console.ReadKey();
            }
        }
        class Base
        {
            public virtual void Func()
            {
                Console.WriteLine("我是一个父类");
            }
        }
        class Sub : Base
        {
            public override void Func()//此处可以直接写成 public void Func()省略掉new,我们姑且称为隐式隐藏
            {
                Console.WriteLine("我是一个子类");
            }
        }

    从重写基类方法的例子,我们得知,对象决定我们访问到的方法,基类对象访问到基类方法,子类对象访问到子类方法.(因隐藏基类方法后,我们的父类引用访问不到子类对象,为了能访问到子类对象,所以就有了重写)

    3.实现多态的例子:

    (1)重写父类方法实现多太

     class Standard
        {
            public virtual void Usb()
            {
                Console.WriteLine("一系列标准条文");
            }
    class Light : Standard
        {
            public override void Usb()
            {
                Console.WriteLine("我是个usb点灯,我亮了哈哈");
            }
        }
    class Phone:Standard
        {
            public override void Usb()
            {
                Console.WriteLine("我是手机,我在充电");
            }
        }
    class Upan : Standard
        {
            public override void Usb()
            {
                Console.WriteLine("我是upan,我存储东西");
            }
        }
    class Wind:Standard
        {
            public override void Usb()
            {
                Console.WriteLine("我是个usb电风扇,我可以吹风哈哈");
            }
        }
     class Program
        {
            static void Main(string[] args)
            {
                while (true)
                {
                    Console.Write("请问你要在usb接口上插上什么设备呢
    ");
                    Console.WriteLine("请输入你要的设备的序号 1.点灯2.手机3.u盘4.usb风扇");
                    string choice = Console.ReadLine();
                    Standard s;
                    switch (choice)
                    {
                        case "1": s = new Light(); break;
                        case "2": s = new Phone(); break;
                        case "3": s = new Upan(); break;
                        case "4": s = new Wind(); break;
                        default: s = new Standard(); break;
                    }
                    if (s!=null)
                    {
                        s.Usb();//多态的实现,一种形式,实现多种功能,根据对象的不同,调用不同子类的方法
                    }
                    else
                    {
                        Console.WriteLine("输入有误");
                    }
                    Console.ReadKey(true);
                    Console.Clear();
                }    
            }
        }

     里氏转换中的例子改用多态实现的代码:

     public class Person//基类,或称为父类
        {
            private string name;
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
            private int age;
            public int Age
            {
                get { return age; }
                set { age = value; }
            }
            private char gender;
            public char Gender
            {
                get { return gender; }
                set { gender = value; }
            }
            public Person(string name, int age, char gender)
            {
                this.Name = name;
                this.Age = age;
                this.Gender = gender;
            }
            public virtual void SayHello()
            {
                Console.WriteLine("我是{0},我今年{1}岁了,我是{2}生", name, age, gender);
            }
        }
     public class Teacher:Person//继承类,或称子类
        {
            public string course;
            public string Cource
            {
                set{course=value;}
                get{return course;}
            }
            private int yearsOfService;
            public int YearsOfService
            {
                set { yearsOfService = value; }
                get { return yearsOfService; }
            }
        
            public override  void SayHello()
            {
                Console.WriteLine("你们好,我是{0},我今年{1}岁了,教书{2}年了,我是{3}老师", Name, Age, yearsOfService, course);
            }
            public Teacher(string name,int age,char gender,string course,int yearsOfService):base( name, age, gender)
                //此处若没写base(name,age,gender)构造方法,便是默认调用Person的无参构造方法即base()
            {
                this.course = course;
                this.yearsOfService = yearsOfService;
            }
        }
        public class Student : Person//继承类Student
        {
            private int classId;
            public int ClassId
            {
                set { classId = value; }
                get { return classId; }
            }
            private string hobby;
            public string Hobby
            {
                set { hobby = value; }
                get { return hobby; }
            }
            public override void SayHello()
            {
                Console.WriteLine("大家好,我是{0},我今年{1}岁了,我是{2}生,我是{3}班的,我喜欢{4}", Name, Age, Gender, classId, hobby);//包含基类的成员,加自己的成员,除了基类的私有成员外,其余成员都能访问到
            }
            public Student(string name,int age,char gender,int classId,string hobby):base(name,age,gender)
            {
                this.classId = classId;
                this.hobby = hobby;
            }
    
        }
     class Program
        {
            static void Main(string[] args)
            {
                Person[] ps = new Person[]{
                    new Teacher("翟群",23,'',"c#",0),
                    new Student("何雄军",24,'',2,"计算机"),
                    new Person("呵呵",23,'')};
                for (int i = 0; i < ps.Length;i++ )
                {
                    ps[i].SayHello();
                }
                Console.ReadKey();
            }
        }

    (2)抽象类抽象方法实现多太

    ■抽象类和抽象方法由abstract修饰

    ■abstract类的使用须注意:

     ♢抽象方法没有抽象体

       ♢抽象成员只能存在于抽象类中

       ♢抽象类可以有非抽象成员

       ♢抽象类派生的非抽象类必须实现抽象方法

       ♢抽象类只能用于基类,无法实例化

     abstract class Standard
        {
            //public virtual void Usb()
            //{
            //    Console.WriteLine("一系列标准条文");
            //}虚方法是要有实现体的方法,如果不需要其实现,,或不知道怎么实现的时候,那么可以使用抽象方法
           public abstract void Usb();
           //抽象方法不允许有实现体,相当于定义的标准,用来让子类实现
           //抽象方法必须在抽象类中
        }
    class Light : Standard
        {
            public override void Usb()
            {
                Console.WriteLine("我是个usb点灯,我亮了哈哈");
            }
        }
     class Phone:Standard
        {
            public override void Usb()
            {
                Console.WriteLine("我是手机,我在充电");
            }
        }
      class Upan : Standard
        {
            public override void Usb()
            {
                Console.WriteLine("我是upan,我存储东西");
            }
        }
    class Wind:Standard
        {
            public override void Usb()
            {
                Console.WriteLine("我是个usb电风扇,我可以吹风哈哈");
            }
        }
     class Program
        {
            static void Main(string[] args)
            {
                while (true)
                {
                    Console.Write("请问你要在usb接口上插上什么设备呢
    ");
                    Console.WriteLine("请输入你要的设备的序号 1.点灯2.手机3.u盘4.usb风扇");
                    string choice = Console.ReadLine();
                    Standard s;
                    switch (choice)
                    {
                        case "1": s = new Light(); break;
                        case "2": s = new Phone(); break;
                        case "3": s = new Upan(); break;
                        case "4": s = new Wind(); break;
                        default: s = null; break;
                    }
                    if (s != null)
                    {
                        s.Usb();//多态的实现,一种形式,实现多种功能,根据对象的不同,调用不同子类的方法
                    }
                    else
                    {
                        Console.WriteLine("输入有误");
                    }
                    Console.ReadKey(true);
                    Console.Clear();
                }
            }
        }

    (3)接口实现多态

    ■抽象的一种抽象的约定(接口是一组函数成员而不实现成员的引用类型)

    ■接口就是用来实现的

    ■语法

      ♢[访问修饰符]interface接口名

      {

        //接口成员定义,成员没有实现,实现被一个分号代替

      }

      ♢接口只有方法,属性,事件,索引的声明

      ♢接口是用来实现的,所有的成员默认为public

      interface IWalkable//定义一个走路的能力接口
        {
            void Walk();//返回类型 方法名(参数列表)
        }
      interface ISound//定义一个发出声音的接口
        {
            void Sound();
        }
     class Car:IWalkable
        {
            public void Walk()
            {
                Console.WriteLine("我是小汽车,我会跑的快");
            }
        }
    class radio:ISound
        {
            public void Sound()
            {
                Console.WriteLine("我是小喇叭,我可以广播呵 啦啦啦");
            }
        }
    abstract class Animal : IWalkable, ISound
        {
            public abstract void Walk();
            public abstract void Sound();
        }
    class Cat:Animal
        {
            public override void Walk()
            {
                Console.WriteLine("我是猫猫,我会走猫步");
            }
    
            public override void Sound()
            {
                Console.WriteLine("我是猫猫,我会喵喵");
            }
        }
    class Person:Animal
        {
            public override void Walk()
            {
                Console.WriteLine("我是人类,我会走路哟");
            }
    
            public override void Sound()
            {
                Console.WriteLine("我是人类,我可以发声哟");
            }
        }
    class Program
        {
            static void Main(string[] args)
            {
                IWalkable[] walkObjects ={
                                           new Person(),
                                           new Cat(),
                                           new Car(),
                                       };
                for (int i = 0; i < walkObjects.Length;i++ )
                {
                    walkObjects[i].Walk();
                }
                ISound[] soundObjects ={
                                           new Person(),
                                           new Cat(),
                                           new radio()
                                       };
                Console.WriteLine("
    =============
    ");
                for (int i = 0; i < soundObjects.Length;i++ )
                {
                    soundObjects[i].Sound();
                }
                Console.ReadKey(true);
            }
        }

     我们可以再为Person类派生一个子类Student,Student类继续重写Walk()和Sound()

    class Student : Person
        {
            public override void Sound()
            {
                Console.WriteLine("我是一个重写Person父类sound()方法的子类方法");
            }
            public override void Walk()
            {
                base.Walk();//这样既可以调用Person的Walk()方法,又有自己的重写方法
                Console.WriteLine("我是重写Person父类的walk方法的子类方法");
            }
        }                                                    

    怎么理解接口就是定义了一个协议或规范?

      我们对一个数字数组进行排序,我们对两个数进行比较时候,系统就会自动默认按数值的大小进行比较。这事因为数字数组默认实现了 IEnumber接口,也就是IEnumber这个接口是一种规范,规定了如果num1-num2>0,则num1比num2大。

     那么如果我们对字符串进行排序呢,或者对一个Person类进行排序。该按照一种什么规范来排?对于字符串,是按照字符串的长度还是字符串字母的排序。对于Person类是按照Person字段里的年龄排序还是身高排序或是其他的呢?所以这时候需要我们自己来定义一个规范,也就是一个借口,指明 按照什么规范进行排序

     下面请代码,首先,我们做一个练习对数组进行排序,升序。

    int[] array=new int[]{21,30,4,87,89,34}
    for(int i=0;i<array.Length-1;i++){
        for(int j=0;j<array.Length-i-1;j++){
            if(array[j]>array[j+1]){
             int temp=array[j];
              array[j]=array[j+1];
              array[j+1]=temp;
            }
        }
    }

    如果对一个字符串的字符长度进行排序,升序

      string[] str = new string[] { "dfjdjf", "afhjdh", "e0", "123" };
        for (int i = 0; i < str.Length-1;i++ )
                {
                    for (int j = 0; j < str.Length - i - 1; j++)
                    {
                        if (str[j].Lenth>str[j+1].Length)
                        {
                            string temp;
                            temp = str[j];
                            str[j] = str[j + 1];
                            str[j + 1] = temp;
                        }
                    }

    对于字符串长度的排序就是数字的大小比较,IEnumber里定义了一个int Compare(int num1,int num2)方法,具体实现为如果num1-num2>0则返回1,如果num1-num2<0,则返回-1,如果num1-num2=0,则返回0。我们将以上对于字符串长度的排序采用为实现接口的手段来实现

    interface Icompare
        {
           int compare(string s1,string s2);
        }
     class IclassCompare:Icompare
        {
    
            public int compare(string s1, string s2)
            {
               if (s1.Length>s2.Length)
               {
                   return 1;
               }
               else if(s1.Length==s2.Length)
               {
                   return 0;
               }
               else
               {
                   return -1;
               }
            }
    }
      class Program
        {
            static void Main(string[] args)
            {
                string[] strs = new string[] { "dfjdjf", "afhjdh", "e0", "123" };
                strsort(new IclassCompare(),strs);
                
            }
            static void strsort( Icompare icom ,params string[] str)
            {
                for (int i = 0; i < str.Length-1;i++ )
                {
                    for (int j = 0; j < str.Length - i - 1; j++)
                    {
                        if (icom.compare(str[j],str[j+1])>0)
                        {
                            string temp;
                            temp = str[j];
                            str[j] = str[j + 1];
                            str[j + 1] = temp;
                        }
                    }
                  
                }
                Console.WriteLine(string.Join(",", str));
                Console.ReadKey();
            }
    }
    View Code

    如果是对字符串进行按字母排序

     interface Icompare1
        {
               int CompareByLetter();
        }
    
       class IclassCompare:Icompare
        {
            public int CompareLetter(string s1, string s2)
            {
                return string.Compare(s1, s2);
            }
        }
     class Program
        {
            static void Main(string[] args)
            {
                string[] strs = new string[] { "dfjdjf", "afhjdh", "e0", "123" };
                sort1(new IclassCompare(),strs);
       
            }
            static void sort1(IclassCompare icom,params string[] strs)
            {
                for (int i = 0; i < strs.Length - 1; i++)
                {
                    for (int j = 0; j < strs.Length - i - 1; j++)
                    {
                        if (icom.CompareLetter(strs[j], strs[j + 1]) > 0)
                        {
                            string temp;
                            temp = strs[j];
                            strs[j] = strs[j + 1];
                            strs[j + 1] = temp;
                        }
                    }
                    Console.WriteLine(string.Join(",", strs));
                    Console.ReadKey();
                }
             }
     }
    View Code
  • 相关阅读:
    正则表达式
    跨域请求/SpringMVC拦截器
    批量导出
    什么是2MSL以及TIME_WAIT的作用
    使用jstack精确找到异常代码的
    nettry 入站事件如何传递到下一个handler
    netty 引用计数器 ,垃圾回收
    elasticsearch 查询优化
    Spark性能优化指南-高级篇(spark shuffle)
    Broadcast与map进行join,避免shuffle,从而优化spark
  • 原文地址:https://www.cnblogs.com/tobecabbage/p/3460984.html
Copyright © 2011-2022 走看看