2015 5.16 C# 继承和多态
类的层次结构有两种基本的构造方式 自顶向下 自底向上
基类的保护成员是指允许派生类的方法代码访问,而不是指通过派生类的对象访问
如果基类中的字段通过公有且可读写的属性进行了封装,那么建议将字段定义为私有的,这样包括其派生类在内的所有其他类型都必须通过属性进行访问
隐藏基类成员
如果派生类中定义了与基类相同的成员,默认情况下基类的成员在派生类中会被隐藏,即派生类成员覆盖了基类成员 用new来修饰提高代码可读性
base 关键字,当派生类隐藏了基类成员时,base关键字就能发挥作用:直接写出的成员名表示派生类的成员,增加了base引用的成员表示被隐藏的基类成员
用base声明创建对象时调用的基类重载构造函数
虚拟方法和重载方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System.Collections.Generic; 2 using System.Linq; 3 using System.Text; 4 5 namespace ConsoleApplication1 6 { 7 class Program 8 { 9 static void Main() 10 { 11 foreach (Automobile a in GetAutos()) 12 { 13 a.Speak(); 14 Console.WriteLine("{0}行驶1000公里需要{1}小时", a.Name, a.Run(1000)); 15 } 16 //Console.ReadLine(); 17 } 18 static Automobile[] GetAutos() 19 { 20 Automobile[] autos = new Automobile[4]; 21 autos[0] = new Bus("客车", 20); 22 autos[1] = new Truck("东风卡车", 30); 23 autos[2] = new Truck("黄河卡车", 45); 24 autos[3] = new Automobile("汽车", 80, 3); 25 return autos; 26 } 27 } 28 29 public class Automobile 30 { 31 private string name; 32 public string Name 33 { 34 get { return name; } 35 } 36 37 private float speed; 38 public float Speed 39 { 40 get { return speed; } 41 } 42 43 private float weight; 44 public float Weight 45 { 46 get { return weight; } 47 set { weight = value; } 48 } 49 50 public Automobile(string name, float speed, float weight) 51 { 52 this.name = name; 53 this.speed = speed; 54 this.weight = weight; 55 } 56 57 public virtual float Run(float distance)//虚拟方法 58 { 59 return distance / speed; 60 } 61 62 public virtual void Speak() 63 { 64 Console.WriteLine("汽车鸣笛……"); 65 } 66 } 67 public class Bus : Automobile 68 { 69 private int passangers; 70 public int Passangers 71 { 72 get { return passangers; } 73 set { passangers = value; } 74 } 75 public Bus(string name, int passangers) 76 : base(name, 60, 10) 77 { 78 this.passangers = passangers; 79 } 80 public override void Speak() 81 { 82 Console.WriteLine("嘀……嘀……"); 83 } 84 } 85 86 public class Truck : Automobile 87 { 88 private float load; 89 public float Load 90 { 91 get { return load; } 92 set { load = value; } 93 } 94 public Truck(string name, int load) 95 : base(name, 50, 15) 96 { 97 this.load = load; 98 } 99 public override float Run(float distance)//重载方法 100 { 101 return (1 + load / Weight / 2) * base.Run(distance); 102 } 103 public override void Speak()//重载方法 104 { 105 Console.WriteLine("叭……叭……"); 106 } 107 } 108 109 }
抽象类和抽象方法(抽象类不能直接用new创建对象,但可以与派生类的实例相关联)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace ConsoleApplication1 7 { 8 class Program 9 { 10 static void Main() 11 { 12 Vehicle v1 = new Train(); 13 v1.Speak(); 14 Console.WriteLine("行驶1000公里需{0}小时", v1.Run(1000)); 15 v1 = new Truck(16, 24); 16 v1.Speak(); 17 Console.WriteLine("行驶1000公里需{0}小时", v1.Run(1000)); 18 Console.ReadLine(); 19 } 20 } 21 22 public abstract class Vehicle 23 { 24 private float speed; 25 public float Speed 26 { 27 get { return speed; } 28 } 29 30 public virtual float Run(float distance) 31 { 32 return distance / speed; 33 } 34 35 public abstract void Speak();//抽象方法:无执行代码 36 37 public Vehicle(float speed) 38 { 39 this.speed = speed; 40 } 41 } 42 43 public class Train : Vehicle 44 { 45 public Train() 46 : base(160) 47 { } 48 49 public override void Speak() 50 { 51 Console.WriteLine("呜……"); 52 } 53 } 54 55 public abstract class Automobile:Vehicle 56 { 57 public Automobile(float speed):base(speed) 58 { } 59 60 public override abstract void Speak();//重载+抽象 61 } 62 63 public class Truck : Automobile 64 { 65 private float weight; 66 public float Weight 67 { 68 get { return weight; } 69 } 70 71 private float load; 72 public float Load 73 { 74 get { return load; } 75 } 76 77 public Truck(int weight, int load) 78 : base(50) 79 { 80 this.weight = weight; 81 this.load = load; 82 } 83 84 public override float Run(float distance) 85 { 86 return (1 + load / Weight / 2 )* base.Run(distance); 87 } 88 89 public override void Speak() 90 { 91 Console.WriteLine("叭……叭……"); 92 } 93 } 94 }
密封类和密封方法
一些类型不允许或是不需要再有派生类型 sealed 密封类是对类继承的截止 密封方法是对类继承中方法重载的截止
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 sing System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace ConsoleApplication1 7 { 8 class Program 9 { 10 static void Main() 11 { 12 Student s1=new Student(101,"王小红"); 13 Console.WriteLine(s1); 14 Student s2=new Graduate(101,"王晓红","张大伟"); 15 Console.WriteLine(s2); 16 Console.WriteLine(s1.Equals(s2)); 17 Console.ReadLine(); 18 } 19 } 20 21 public class Student 22 { 23 private string name; 24 public string Name 25 { 26 get { return name; } 27 } 28 29 private int id; 30 public int ID 31 { 32 get { return id; } 33 } 34 35 public Student(int id, string name) 36 { 37 this.id = id; 38 this.name = name; 39 } 40 41 public override string ToString() 42 { 43 return string.Format("学号{0},姓名{1}", id, name); 44 } 45 46 public sealed override bool Equals(object obj) 47 { 48 if (obj is Student && ((Student)obj).id == this.id) 49 return true; 50 else 51 return false; 52 } 53 } 54 55 public class Graduate : Student 56 { 57 private string supervisor; 58 public string Supervisor 59 { 60 get { return supervisor; } 61 set { supervisor = value; } 62 } 63 64 public Graduate(int id, string name, string supervisor) 65 : base(id, name) 66 { 67 this.supervisor = supervisor; 68 } 69 70 public override string ToString() 71 { 72 return base.ToString() + ",导师:" + supervisor; 73 } 74 } 75 }