C# 继承和接口
继承
继承(以及封装和多态性)是面向对象的编程的三个主要特征之一。通过继承,可以创建重用、扩展和修改在其他类中定义的行为的新类。其成员被继承的类称为 “基类” ,继承这些成员的类称为 “派生类” 。派生类只能有一个直接基类。但是,继承是可以传递的。如果 ClassC 派生自 ClassB ,并且 ClassB 派生自 ClassA ,则 ClassC会继承在 ClassB 和 ClassA 中声明的成员。
继承的代码实现:
1 /// <summary> 2 /// 构建一个工作项的业务类(缺省继承自基类Object) 3 /// </summary> 4 public class WorkItem 5 { 6 private static int currentID; // 用于存储最新加入的工作项的ID的静态字段 7 8 protected int ID { get; set; } // 工作项标识符 9 protected string Title { get; set; } // 名称 10 protected string Description { get; set; } // 说明 11 protected TimeSpan JobLength { get; set; } // 所需时长 12 13 public WorkItem() 14 { 15 ID = 0; 16 Title = "缺省的工作名称"; 17 Description = "简单的描述"; 18 JobLength = new TimeSpan(); 19 } 20 21 public WorkItem(string title,string desc,TimeSpan joblen) 22 { 23 this.ID = GetNextID(); 24 this.Title = title; 25 this.Description = desc; 26 this.JobLength = joblen; 27 } 28 29 /// <summary> 30 /// 静态构造函数,用来初始化静态属性 31 /// </summary> 32 static WorkItem() 33 { 34 currentID = 0; 35 } 36 37 /// <summary> 38 /// 构建下一个对象的ID 39 /// </summary> 40 /// <returns></returns> 41 protected int GetNextID() 42 { 43 return ++currentID; 44 } 45 46 /// <summary> 47 /// 更新 48 /// </summary> 49 /// <param name="title"></param> 50 /// <param name="joblen"></param> 51 public void Update(string title,TimeSpan joblen) 52 { 53 this.Title = title; 54 this.JobLength = joblen; 55 } 56 57 public override string ToString() 58 { 59 return String.Format("{0}-{1}", this.ID, this.Title); 60 } 61 } 62 63 /// <summary> 64 /// 变更工作项请求 65 /// </summary> 66 public class ChangeRequest : WorkItem 67 { 68 protected int originalItemID { get; set; } // 原来安排工作项的ID 69 70 public ChangeRequest() 71 { 72 73 } 74 public ChangeRequest(string title,string desc,TimeSpan joblen,int originalID) 75 { 76 this.ID = GetNextID(); 77 this.Title = title; 78 this.Description = desc; 79 this.JobLength = joblen; 80 81 this.originalItemID = originalID; 82 } 83 }
继承的实际应用
1 /// <summary> 2 /// 继承的实际应用 3 /// </summary> 4 public static class Inheritence 5 { 6 public static void ToInheritence() 7 { 8 // 定义一个工作项 9 WorkItem item = new WorkItem("修复 Bugs", "修复当前代码的全部 bug", new TimeSpan(3, 4, 0,0)); 10 11 // 定义一个工作项变更要求 12 ChangeRequest change = new ChangeRequest("变更基类设计内容", "添加类成员", new TimeSpan(4, 0, 0), 1); 13 14 Console.WriteLine(item.ToString()); 15 16 //Console.WriteLine(change.ToString()); 17 18 change.Update("进一步变更基类设计内容", new TimeSpan(4, 0, 0)); 19 20 Console.WriteLine(change.ToString()); 21 Console.ReadKey(); 22 } 23 }
抽象类(abstract)
抽象类不能实例化,抽象类的用途是提供一个可供多个派生类共享的通用基类定义。例如,类库可以定义一个抽象类,将其用作多个类库函数的参数,并要求使用该库的程序员通过创建派生类类提供自己的类实现(说明:不完整且必须在派生类中实现的类和类成员)
相关代码:
1 /// <summary> 2 /// 抽象类,不能实例化(一个没有构造函数的类) 3 /// 用途是提供一个可供多个派生类共享的通用基类定义(如: 4 /// 类库可以定义一个抽象类,将其用作多个类库函数的参数,并要求使用该类库的程序员通过创建派生类来提供自己的类实现 5 /// </summary> 6 public abstract class StudentUpdateLog 7 { 8 public Guid ID { get; set; } 9 public DateTime UpdateTime { get; set; } // 更新时间 10 public string Description { get; set; } // 变更说明 11 12 public virtual Student Student { get; set; } // 关联学生 13 14 public abstract void SetDescription(string desc); // 设置变更说明 15 } 16 17 /// <summary> 18 /// 学生教学班变更记录 19 /// </summary> 20 public class StudentSchoolClassUpdateLog : StudentUpdateLog 21 { 22 public SchoolClass OrogianlSchoolClass { get; set; } // 原来班级 23 public SchoolClass CurrentSchoolClass { get; set; } // 当前 24 25 public StudentSchoolClassUpdateLog() 26 { 27 this.ID = Guid.NewGuid(); 28 this.UpdateTime = DateTime.Now; 29 } 30 31 /// <summary> 32 /// 如果在抽象类中定义了方法,那么必须在它的派生类中实现 33 /// </summary> 34 /// <param name="desc"></param> 35 public override void SetDescription(string desc) 36 { 37 this.Description = desc; 38 } 39 }
接口类
(接口包含类或结构可以实现的一组相关功能的定义)
。接口类似于抽象基类。实现接口的任何类或接口多必须实现其所有成员。
。接口无法直接进行实例。其成员由实现接口的任何类或接口来实现。
。接口可以包含事件、索引器、方法和属性。
。一个类或结构可以实现多个接口。
。一个类可以继承一个基类,还可以实现一个或多个接口。
1 /// <summary> 2 /// 用于描述相等性的接口 3 /// </summary> 4 /// <typeparam name="T">待指定类型的类型</typeparam> 5 public interface IEquatable<T> 6 { 7 string GetMake(); // 获取制造商 8 string GetModle(); // 获取类型 9 string GetYear(); // 获取年份 10 11 /// <summary> 12 /// 只定义方法、返回值、参数、没有定义任何具体的实现 13 /// </summary> 14 /// <param name="obj">T所限定类型的对象</param> 15 /// <returns></returns> 16 bool Equals(T obj); 17 } 18 19 public class Car : IEquatable<Car> 20 { 21 public string Make { get; set; } 22 public string Modle { get; set; } 23 public string Year { get; set; } 24 25 public Car(string make,string modle,string year) 26 { 27 this.Make = make; 28 this.Modle = modle; 29 this.Year = year; 30 } 31 32 // 实现 IEquatable<T> 接口 33 public bool Equals(Car obj) 34 { 35 if (this.Make == obj.Make && this.Modle == obj.Modle && this.Year == obj.Year) 36 return true; 37 else 38 return false; 39 } 40 41 // 实现接口类 IEquatable<T> 的成员方法 42 public string GetMake() 43 { 44 return Make; 45 } 46 47 public string GetModle() 48 { 49 return Modle; 50 } 51 52 public string GetYear() 53 { 54 return Year; 55 } 56 } 57 58 /// <summary> 59 /// 接口类的实现 60 /// </summary> 61 public static class InterfaceClass 62 { 63 public static void ToInterface() 64 { 65 // 创建 Car 实例 66 Car car1 = new Car("宝马", "跑车", "2017"); 67 Car car2 = new Car("宝马", "跑车", "2016"); 68 bool b= car1.Equals(car2); 69 if (b == true) 70 Console.WriteLine("相同"); 71 else 72 Console.WriteLine("额不相同"); 73 74 // 声明一个转型的 IEquatable,没有创建 75 IEquatable<Car> hehe = (IEquatable<Car>)car1; 76 77 Console.WriteLine("Make:{0},Model{1},Year{2}", car1.Make, car1.Modle, car1.Year); 78 79 Console.WriteLine("hMake:{0},hModel{1},hYear{2}", hehe.GetMake(), hehe.GetModle(), hehe.GetYear()); 80 81 Console.ReadKey(); 82 } 83 }