父类与子类相互转换
1 /// <summary> 2 /// 动物类(父类) 3 /// </summary> 4 class Animal 5 { 6 public string Name { get; set; }//名字 7 public string Color { get; set; }//颜色 8 public string Kind { get; set; }//种类 9 public string Favorite { get; set; }//喜好 10 11 public Animal() { } 12 public Animal(string name, string color, string kind) 13 { 14 this.Name = name; 15 this.Color = color; 16 this.Kind = kind; 17 } 18 //自我介绍 19 public void Introduce() 20 { 21 string info = string.Format("我是漂亮的{0},我的名字叫{1},身穿{2}的衣服,我爱吃{3}!", this.Kind, Name, Color, Favorite); 22 Console.WriteLine(info); 23 } 24 }View Code
给Cat和Dog分别添加Have()方法:
1 /// <summary> 2 /// 玩具猫类 3 /// </summary> 4 class Cat:Animal//继承Animal类 5 { 6 public Cat() { }//默认调用父类的无参构造函数,若此时父类并没有无参构造函数,则报错 7 public Cat(string name, string color, string kind, string favorite) : base(name, color, kind) 8 { 9 this.Favorite = favorite; 10 } 11 //跳舞 12 public void Dancing() 13 { 14 base.Introduce();//调用父类的方法 15 Console.WriteLine("下面给大家表演,请大家鼓掌!"); 16 } 17 18 public void Have() 19 { 20 Console.WriteLine("吃烤鱼!"); 21 }View Code
1 /// <summary> 2 /// 玩具狗类 3 /// </summary> 4 class Dog:Animal//继承Animal类 5 { 6 public Dog(string name, string color, string kind) 7 { 8 this.Name = name;//使用this关键字访问父类成员 9 this.Color = color; 10 this.Kind = kind; 11 } 12 13 public Dog() { }//隐式调用:默认调用父类的无参构造函数,若此时父类并没有无参构造函数,则出错。 14 15 public Dog(string name, string color, string kind, string favorite) : base(name, color, kind) 16 {//显示调用 17 this.Favorite = favorite; 18 } 19 public void Race() 20 { 21 base.Introduce();//使用base关键字调用父类方法 22 Console.WriteLine("下面给大家表演赛跑,请大家鼓掌!"); 23 } 24 25 public override void Have() 26 { 27 Console.WriteLine("吃骨头!"); 28 } 29 }View Code
调用:
1 static void Main(string[] args) 2 { 3 //创建两个对象 4 Cat objCat = new Cat("球球", "黄色", "小花猫", "小鱼"); 5 Dog objDog = new Dog("团团", "黑色", "小黑狗", "骨头"); 6 7 //将子类对象添加到父类集合 8 List<Animal> list = new List<Animal>(); 9 10 //List<object> list1 = new List<object>(); 11 //添加时自动将子类转换为父类类型(父类类型可以添加子类对象,子类自动转换成父类类型) 12 list.Add(objCat); 13 list.Add(objDog); 14 15 //取出对象(取出时必须判断属于哪一个子类对象,父类类型对象必须强制转换成对应子类对象,才能调用子类方法。) 16 foreach (Animal obj in list) 17 { 18 if (obj is Cat)//判断原始类型 19 ((Cat)obj).Have(); 20 else 21 ((Dog)obj).Have(); 22 } 23 24 }View Code
从上述代码示例中我们可以看到,父类类型可以添加子类对象,子类自动转换成父类类型。而在取出对象时,需要判断对象的原始类型属于哪一个对象,然后强制转换成对应子类对象,才能调用子类的方法。下面介绍如何使用抽象类和抽象方法优化上述示例代码。
使用抽象类和抽象方法
在父类中定义一个抽象方法:
1 /// <summary> 2 /// 动物类(父类) 3 /// </summary> 4 abstract class Animal 5 { 6 public string Name { get; set; }//名字 7 public string Color { get; set; }//颜色 8 public string Kind { get; set; }//种类 9 public string Favorite { get; set; }//喜好 10 11 public Animal() { } 12 public Animal(string name, string color, string kind) 13 { 14 this.Name = name; 15 this.Color = color; 16 this.Kind = kind; 17 } 18 //自我介绍 19 public void Introduce() 20 { 21 string info = string.Format("我是漂亮的{0},我的名字叫{1},身穿{2}的衣服,我爱吃{3}!", this.Kind, Name, Color, Favorite); 22 Console.WriteLine(info); 23 } 24 25 /// <summary> 26 /// 定义一个抽象方法 27 /// </summary> 28 public abstract void Have();View Code
在子类中重写(override)父类未实现的方法(抽象方法):
1 /// <summary> 2 /// 玩具猫类 3 /// </summary> 4 class Cat:Animal//继承Animal类 5 { 6 public Cat() { }//默认调用父类的无参构造函数,若此时父类并没有无参构造函数,则报错 7 public Cat(string name, string color, string kind, string favorite) : base(name, color, kind) 8 { 9 this.Favorite = favorite; 10 } 11 //跳舞 12 public void Dancing() 13 { 14 base.Introduce();//调用父类的方法 15 Console.WriteLine("下面给大家表演,请大家鼓掌!"); 16 } 17 18 /// <summary> 19 /// 重写父类的Have()方法 20 /// </summary> 21 public override void Have() 22 { 23 Console.WriteLine("吃烤鱼!"); 24 } 25 26 }View Code
1 /// <summary> 2 /// 玩具狗类 3 /// </summary> 4 class Dog:Animal//继承Animal类 5 { 6 public Dog(string name, string color, string kind) 7 { 8 this.Name = name;//使用this关键字访问父类成员 9 this.Color = color; 10 this.Kind = kind; 11 } 12 13 public Dog() { }//隐式调用:默认调用父类的无参构造函数,若此时父类并没有无参构造函数,则出错。 14 15 public Dog(string name, string color, string kind, string favorite) : base(name, color, kind) 16 {//显示调用 17 this.Favorite = favorite; 18 } 19 public void Race() 20 { 21 base.Introduce();//使用base关键字调用父类方法 22 Console.WriteLine("下面给大家表演赛跑,请大家鼓掌!"); 23 } 24 25 /// <summary> 26 /// 重写父类的Have()方法 27 /// </summary> 28 public override void Have() 29 { 30 Console.WriteLine("吃骨头!"); 31 } 32 }View Code
调用:
1 static void Main(string[] args) 2 { 3 //创建两个对象 4 Cat objCat = new Cat("球球", "黄色", "小花猫", "小鱼"); 5 Dog objDog = new Dog("团团", "黑色", "小黑狗", "骨头"); 6 7 //将子类对象添加到父类集合 8 List<Animal> list = new List<Animal>(); 9 10 //添加时自动将子类转换为父类类型 11 list.Add(objCat); 12 list.Add(objDog); 13 14 //取出对象 15 foreach (Animal obj in list) 16 { 17 obj.Have();//不再需要类型判断 18 } 19 20 }View Code
使用抽象类和抽象方法后,我们发现无需对取出对象进行类型判断,程序也能自动调用对应子类的实现方法(由虚拟机完成)。充分体现了面向对象编程的"多态"思想,使用"继承多态"机制很好地解决了系统扩展问题。
总结抽象类与抽象方法
抽象类的概念与使用要点:
1.使用关键字abstract修饰的类,称为抽象类。
2.抽象类只是用来列举一个类所具有的行为,不能单独通过创建对象来使用,如 Animal animal=new Animal() (×)。
3.抽象类中可以有抽象方法,也可以没有任何抽象方法。但是有抽象方法的类一定是抽象类。
4.抽象类不能是静态类(static)或密封类(sealed)。注:密封类不能被重写。
抽象方法的概念与使用要点:
1.再抽象类中使用abstract修饰的方法,称之为抽象方法。
2.抽象方法必须再抽象类中定义,不能再普通类中使用(即有抽象方法的类一定是抽象类)。
3.抽象方法只是一个方法的声明,不能有任何方法体。如:public abstract void Have();
4.抽象方法仅仅表示一个应该具有的行为,具体实现由子类实现。
5.抽象方法再子类中被实现(重写)必须使用关键字override。
6.子类必须重写父类的所有抽象方法,除非子类本身也是抽象类。