面向对象的多态 (很重要)
概念:让一个对象能够表现出多种的状态(类型)
在这之前:每个父类都要强转成子类,才可以调用每个子类的方法
//概念:能让一个对象表现出多种的状态(类型) //实现多态的3中手段:1、虚方法 2、抽象类 3、接口 Chinese cn1 = new Chinese("韩梅梅"); Chinese cn2 = new Chinese("李雷"); Japenese ja1 = new Japenese("井田子"); Japenese ja2 = new Japenese("松下子"); Korea ko1 = new Korea("金德善"); Korea ko2 = new Korea("金正焕"); American a1 = new American("奥尼尔"); American a2 = new American("科比"); Person[] pers = { cn1, cn2, ja1, ja2, ko1, ko2, a1, a2 }; for (int i = 0; i < pers.Length ; i++) { if(pers[i] is Chinese ) { ((Chinese)pers[i] ).SayHello(); } else if (pers[i] is Japenese ) { ((Japenese)pers[i]).SayHello(); } else if(pers[i] is Korea ) { ((Korea)pers[i]).SayHello(); } else { ((American)pers[i]).SayHello(); } } Console.ReadKey(); } }
实现多态的手段:
1、虚方法:
步骤:
1)将父类的方法标记为虚方法,使用关键字 virtual,这个函数可以被子类重新写一遍
在子类的方法中使用override,这个方法被重写了一遍。具体调用哪一个子类的方法,取决于装的是谁的对象
就不需要一大堆的强转,只需要写一句就行。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 面向对象的多态 { class Program { static void Main(string[] args) { //概念:能让一个对象表现出多种的状态(类型) //实现多态的3中手段:1、虚方法 2、抽象类 3、接口 Chinese cn1 = new Chinese("韩梅梅"); Chinese cn2 = new Chinese("李雷"); Japenese ja1 = new Japenese("井田子"); Japenese ja2 = new Japenese("松下子"); Korea ko1 = new Korea("金德善"); Korea ko2 = new Korea("金正焕"); American a1 = new American("奥尼尔"); American a2 = new American("科比"); Person[] pers = { cn1, cn2, ja1, ja2, ko1, ko2, a1, a2,new English ("green"),new English ("maria") }; for (int i = 0; i < pers.Length ; i++) { //if(pers[i] is Chinese ) //{ // ((Chinese)pers[i] ).SayHello(); //} //else if (pers[i] is Japenese ) //{ // ((Japenese)pers[i]).SayHello(); //} //else if(pers[i] is Korea ) //{ // ((Korea)pers[i]).SayHello(); //} //else //{ // ((American)pers[i]).SayHello(); //} pers[i].SayHello(); } Console.ReadKey(); } } public class Person { private string _name;//字段 public string Name//属性 { get { return _name; } set{ _name = value; } } public Person(string name)//构造函数 { this.Name = name; } public virtual void SayHello()//方法,加个virtual,让他变成虚方法 { Console.WriteLine("我是人类"); } } public class Chinese:Person { public Chinese (string name) :base(name) { } public override void SayHello() { Console.WriteLine("我是中国人"); } } public class Japenese:Person { public Japenese (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); } } public class English:Person { public English (string name) :base(name) { } public override void SayHello() { Console .WriteLine ("我是英国人"); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 练习 { class Program { static void Main(string[] args) { //真的鸭子嘎嘎叫 木头鸭子吱吱叫 橡皮鸭子叽叽叫 RealDuck rd = new RealDuck(); MuDuck md = new MuDuck(); XiDuck xd = new XiDuck(); RealDuck[] ducksBark = { rd, md, xd }; for (int i = 0; i < ducksBark .Length ; i++) { ducksBark[i].Bark(); } Console.ReadKey(); } } public class RealDuck { public virtual void Bark() { Console.WriteLine("真的鸭子嘎嘎叫"); } } public class MuDuck:RealDuck { public override void Bark() { Console.WriteLine("木头鸭子吱吱叫"); } } public class XiDuck:RealDuck { public override void Bark() { Console.WriteLine("橡皮鸭子叽叽叫"); } } }
再加一个练习:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 再做一个练习 { class Program { //员工九点打卡,经理10点打卡,程序员不打卡 static void Main(string[] args) { Employee em = new Employee(); Manager ma = new Manager(); Programer pro = new Programer(); Employee[] ems = { ma, pro, em }; for (int i = 0; i <ems.Length ; i++) { ems[i].DaKa(); } Console.ReadKey(); } } public class Employee//员工的意思 { public virtual void DaKa() { Console.WriteLine("九点打卡"); } } public class Manager:Employee { public override void DaKa() { Console.WriteLine("我是10点打卡"); } } public class Programer:Employee { public override void DaKa() { Console.WriteLine("我不打卡"); } } }
2)抽象类
当父类中的方法不知道如何去实现的时候,可以考虑将父类写成抽象类,将方法写成抽象方法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 抽象类 { class Program { static void Main(string[] args) { //狗狗会叫,猫咪也会叫 //Animal an = new Animal();//抽象类不允许创建对象,因为里面什么也没有,创建也没意义 Animal dog = new Dog(); Animal cat = new Cat(); Animal[] an = { dog, cat }; for (int i = 0; i < an.Length ; i++) { an[i].Bark(); } Console.ReadKey(); } } public abstract class Animal //标记一个类为抽象类 用abstract来标记 { public abstract void Bark();//抽象方法是不允许有方法体的,因为我们不知道如何去实现这个方法,抽象的 } public class Dog:Animal { public override void Bark() { Console.WriteLine("狗狗汪汪叫"); } } public class Cat:Animal { public override void Bark() { Console.WriteLine("猫猫喵喵叫"); } } }
抽象类的特点:
1、抽象成员必须标记为abstract,并且不能有任何实现
2、抽象成员必须在抽象类中
3、抽象成员不能被实例化
4、子类继承抽象类后,必须把父类中的所有对象成员都重写
5、抽象成员的访问修饰符不能是private
6、在抽象类中可以包含实例成员。并且抽象类的实例成员可以不被子类实现
7、抽象类是有构造函数的,虽然不能被实例化
8、如果父类的抽象方法中有参数,那么,继承这个抽象父类的子类在重写父类的方法时必须传入对应的参数
如果抽象父类的抽象方法中有返回值,那么子类在重写这个抽象方法的时候,也必须要传入返回值
=================================================================================
如果父类中的方法有默认的实现,并且父类需要被实例化,这时可以考虑将父类定义成一个普通类,用虚方法来实现
如果父类中的方法没有默认实现,父类也不需要被实例化,则可以将该类定义为抽象类-