黑马程序员--多态

--------------------- 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接口上插上什么设备呢\n");
                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接口上插上什么设备呢\n");
                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("\n=============\n");
            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方法的子类方法");
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
多态是面向对象编程中的一个重要概念,它允许不同类型的对象对同一个消息做出不同的响应。基于多态的冲突通常是指在继承关系中存在多个同名方法,导致在调用时产生歧义或冲突的情况。 在黑马程序员的教学中,关于基于多态的冲突一般会涉及到两种情况: 1. 方法重载冲突:方法重载是指在同一个类中存在多个同名方法,但它们的参数类型和/或个数不同。当我们调用这个方法时,编译器会根据参数类型选择最合适的方法。但如果存在多个方法都符合调用要求,就会产生冲突。这种情况下,编译器无法确定到底应该调用哪个方法,会报错。 2. 方法覆盖冲突:方法覆盖是指子类重写了父类中的同名方法。当我们通过父类的引用调用这个方法时,实际执行的是子类中重写的方法。但如果存在多个子类同时重写了这个方法,并且我们使用父类引用指向不同的子类对象,就会产生冲突。这种情况下,编译器同样无法确定到底应该调用哪个方法,会报错。 为了解决基于多态的冲突,我们可以采取以下方法: 1. 方法重载冲突:避免在同一个类中定义多个同名方法,或者通过修改参数类型和/或个数来消除冲突。 2. 方法覆盖冲突:使用强制类型转换或者将父类引用指向具体的子类对象,明确调用具体的重写方法。 在实际开发中,我们需要注意避免基于多态的冲突,保持代码的清晰和可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值