面向对象三大特性:封装,继承与多态,这里讲一下后两个特性。
继承
继承:指一个对象延续另一个对象的特征(属性和方法),并且有自己的个性特征(属性和方法)。
必要性:代码复用,避免重复;一处更新,处处更新。与封装不同的是,封装主要是封装一个方法、一个类,使用时直接调用不能更改;继承主要讲需要的属性和方法(主要是方法)进行“封装”,且要使用时还可以继续扩展自己的特性(继续增加、修改属性和方法)。
使用广泛:C#里,Object类是所有类的基类,winform里面所有控件都继承于Control类。
父类与子类:当A继承与B时,A是子类(或叫派生类),B是父类(或叫基类或超类)。
举例说明一下继承的好处
需求说明:
设计玩具猫、玩具狗相关程序,要求:
属性:姓名,自身颜色,自己类别,喜好食物
动作:自我介绍,跳舞,赛跑
常规实现:
Models--Cat
1 namespace InheritanceTest 2 { 3 class Cat 4 { 5 public string Name { get; set; } 6 public string Color { get; set; } 7 public string Kind { get; set; } 8 public string Favorite { get; set; } 9 10 public void Introduce() 11 { 12 Console.WriteLine("Hi, My name is{0}, I‘m a {1}, I‘m in {2}, and I like eat {3} very much! ",Name,Kind, Color,Favorite); 13 } 14 15 public void Dancing() 16 { 17 Console.WriteLine("Now I dancing for you!"); 18 } 19 20 } 21 }
Models--Dog
1 namespace InheritanceTest 2 { 3 class Dog 4 { 5 public string Name { get; set; } 6 public string Color { get; set; } 7 public string Kind { get; set; } 8 public string Favorite { get; set; } 9 10 public void Introduce() 11 { 12 Console.WriteLine("Hi, My name is{0}, I‘m a {1}, I‘m in {2}, and I like eat {3} very much! ", Name, Kind, Color, Favorite); 13 } 14 15 public void Running() 16 { 17 Console.WriteLine("I can run very fast!"); 18 } 19 } 20 }
Program
1 namespace InheritanceTest 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 Cat cat = new Cat() 8 { 9 Name="kitty", 10 Kind="cat", 11 Color="white", 12 Favorite="fish" 13 }; 14 cat.Introduce(); 15 cat.Dancing(); 16 17 Console.WriteLine(); 18 19 Dog dog = new Dog() 20 { 21 Name = "David", 22 Kind = "dog", 23 Color = "brown", 24 Favorite = "bone" 25 }; 26 dog.Introduce(); 27 dog.Running(); 28 29 Console.ReadLine(); 30 } 31 } 32 }
结果:
问题提出:
出现代码重复:
使用继承来解决这个问题:
增加父类--Animal来存放重复的代码
1 class Animal 2 { 3 public string Name { get; set; } 4 public string Color { get; set; } 5 public string Kind { get; set; } 6 public string Favorite { get; set; } 7 8 public void Introduce() 9 { 10 Console.WriteLine("Hi, My name is{0}, I‘m a {1}, I‘m in {2}, and I like eat {3} very much! ", Name, Kind, Color, Favorite); 11 } 12 }
改一下Dog、Cat:
1 class Dog:Animal 2 { 3 public void Running() 4 { 5 Console.WriteLine("I can run very fast!"); 6 } 7 } 8 9 //要写在各自的类里面,这里为了省事放在一起了 10 11 class Cat:Animal 12 { 13 public void Dancing() 14 { 15 Console.WriteLine("Now I dancing for you!"); 16 } 17 }
Program里面不需要修改,我们可以一样得到上面的结果,这就是使用继承的好处。
继承使用的步骤与特点:
抽象公共部分,放到特定类,即父类;
其他类继承父类,即可拥有父类的特征(属性和方法);
在子类中再添加自己的特征(属性和方法)。
继承中的构造函数
刚刚是使用对象初始化器来实现属性的赋值的,下面使用构造函数来赋值的例子,介绍this、base关键字的使用。
Models--Animal、Cat、Dog添加构造函数(注意:Animal必须要具有无参构造函数)
1 //Animal 2 public Animal() { } 3 public Animal(string name,string color,string kind) 4 { 5 this.Name = name; 6 this.Color = color; 7 this.Kind = kind; 8 } 9 10 //Cat 11 public Cat(string name, string color, string kind, string favorite) 12 { 13 this.Name = name; 14 this.Color = color; 15 this.Kind = kind; 16 this.Favorite = favorite; 17 } 18 19 //Dog 20 public Dog(string name, string color, string kind, string favorite) 21 { 22 this.Name = name; 23 this.Color = color; 24 this.Kind = kind; 25 this.Favorite = favorite; 26 }
Program改写:
1 static void Main(string[] args) 2 { 3 Cat cat = new Cat("kitty", "cat", "white", "fish"); 4 cat.Introduce(); 5 cat.Dancing(); 6 7 Console.WriteLine(); 8 9 Dog dog = new Dog("David", "dog", "brown", "bone"); 10 dog.Introduce(); 11 dog.Running(); 12 13 Console.ReadLine(); 14 }
再次出现代码重复:
使用base关键字来优化:
优化Models--Dog、Cat构造函数
public Dog(string name, string color, string kind, string favorite):base(name, color, kind) { this.Favorite = favorite; } public Cat(string name, string color, string kind, string favorite):base(name, color, kind) { this.Favorite = favorite; }
这里使用了base关键字,该关键字除了可以调用父类的构造方法,还可以调用父类的属性和方法,使用关键字base能将逻辑变得清晰,this关键字则是表示自己类里面的属性和方法,与base做区分。
protected关键字限制了父类的某个成员只能被其子类访问,但是如果在父类里面使用public去调用protected,依旧是可以访问带protected的成员,但是给带protected的属性赋值只能通过构造函数的方式。