黑马程序员--多态

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