---------------------- 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(); } }
如果是对字符串进行按字母排序
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(); } } }