继承能够定义可重用、扩展或修改父类行为的子类。但基类的静态构造函数、实例构造函数和析构函数不能被派生类继承。
在下面实例中,定义一个基类 Publication 用于表示任何类型的出版物以及派生至 Publication 的其他类型 Book 类,由此也可以扩展为定义其他类型如:Magazine、Journal、Newspaper 和 Article。
在设计基类 Publication 时我们必须考虑到如下关系:
1. 要在基类中添加哪些成员
2. 基类是否用作派生类模板的抽象基类
3. 类层次结构的扩展空间大小,要开发包含三个或多个的类的层次结构,如 Publication 是 Periodical 的基类,又可以是 Magazine 和 Journal 的基类
4. 能否重写基类实现的代码,如果容许重写,必须在基类中使用关键字 virtual,派生类才能允许重写基类方法。
5. 派生类是否必须继承结构的终结类,且本身不被用作其他派生类的基类,这时可以用 sealed 关键字来标识该类
先定义一个出版物类型的枚举
- public enumPublicationType:long
- {
- [Description("报纸")]
- Newspaper=1,
- [Description("杂志")]
- Magazine =2,
- [Description("书籍")]
- Book=3
- }
再定义 Publication 抽象基类
- public abstract class Publication {
- private bool published = false;
- private DateTime datePublished;
- private int totalPages;
- public Publication(string title, string publisher, PublicationType type) {
- if (string.IsNullOrWhiteSpace(title)) throw new ArgumentNullException("title can not be null or white space");
- Title = title;
- if (string.IsNullOrWhiteSpace(publisher)) throw new ArgumentNullException("publisher can not be null or white space");
- Publisher = publisher;
- Type = type;
- }
- public string Publisher {
- get;
- }
- public string Title {
- get;
- }
- public PublicationType Type {
- get;
- }
- public string CopyrightName {
- get;
- private set;
- }
- public int CopyrightDate {
- get;
- private set;
- }
- public int Pages {
- get {
- return totalPages;
- }
- set {
- if (value < 0) throw new ArgumentOutOfRangeException("The number of pages cannot be zero or negative");
- totalPages = value;
- }
- }
- public string GetPublicationDate() {
- if (!published) return "NYP";
- else return datePublished.ToString("d");
- }
- public void Publish(DateTime datePublished) {
- published = true;
- this.datePublished = datePublished;
- }
- /// <summary>
- /// 定义所有权名称和期限
- /// </summary>
- /// <param name="copyrightName"></param>
- /// <param name="copyrightDate"></param>
- ///<remarks></remarks>
- public void Copyright(string copyrightName, int copyrightDate) {
- if (string.IsNullOrEmpty(copyrightName)) throw new ArgumentNullException("The copyright name can not be null or empty");
- CopyrightName = copyrightName;
- var currentYear = DateTime.Now.Year;
- if (copyrightDate < currentYear - 10 || copyrightDate > currentYear + 2) throw new ArgumentOutOfRangeException($ "the copyright year must be validate");
- CopyrightDate = copyrightDate;
- }
- public override string ToString() = >Title;
- }
Book 表示一种类型的出版物,继承至 Publication
- public sealed class Book: Publication {
- public Book(string title, string guid, string author, string publisher) : base(title, publisher, PublicationType.Book) {
- if (string.IsNullOrEmpty(guid)) throw new ArgumentNullException("GUID can not be null or empty");
- GUID = guid;
- Author = author;
- }
- public string GUID {
- get;
- }
- public string Author {
- get;
- }
- public decimal Price {
- get;
- private set;
- }
- public string Currency {
- get;
- private set;
- }
- /// <summary>
- /// 设置新的价格返回旧价格
- /// </summary>
- /// <param name="price"></param>
- /// <param name="currency"></param>
- /// <remarks></remarks>
- /// <returns>旧价格</returns>
- public decimal SetPrice(decimal price, string currency) {
- if (price < 0) throw new ArgumentOutOfRangeException("price can not be negative");
- var oldPrice = Price;
- Price = price;
- if (currency.Length != 3) throw new ArgumentNullException("the currency is a 3-character string");
- Currency = currency;
- return oldPrice;
- }
- public override bool Equals(object obj) {
- var book = obj as Book;
- return book == null ? false: GUID.Equals(book.GUID);
- }
- public override int GetHashCode() = >GUID.GetHashCode();
- public override string ToString() = >$ "{(string.IsNullOrEmpty(Author) ? "" : Author + ",
- ")}{Title}";
- }
在代码图中查看 Book 和 Publication 类的依赖关系和类中成员的引用关系
使用反射分别获取 Book 和 Publication 类的成员列表
- class Program
- {
- static voidMain(string[] args)
- {
- vartPublication =typeof(Publication);
- vartBook =typeof(Book);
- varflags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
- varmembersPublication = tPublication.GetMembers(flags);
- varmembersBook = tBook.GetMembers(flags);
- OutputClassInfo(tPublication, membersPublication);
- OutputClassInfo(tBook, membersBook);
- Console.ReadKey();
- }
- private static void OutputClassInfo(Type t, MemberInfo[] members)
- {
- Console.WriteLine($"Type {t.Name} has {members.Length} members:");
- foreach(varmemberin members)
- {
- varaccess =string.Empty;
- varstat =string.Empty;
- if(memberis MethodBase method)
- {
- if (method.IsPublic)
- access ="Public";
- else if (method.IsPrivate)
- access ="Private";
- else if (method.IsFamily)
- access ="Protected";
- else if (method.IsAssembly)
- access ="Internal";
- else if (method.IsFamilyOrAssembly)
- access ="Protected Internal";
- if (method.IsStatic)
- stat ="Static";
- }
- varoutput = $"{member.Name} ({member.MemberType}): {access}{stat}, Declared by {member.DeclaringType}";
- Console.WriteLine(output);
- }
- }
从输出结果分析可得出:
1、Publication 和 Book 都隐式继承自基类
2、派生类只能有一个一个直接基类,当然可以隐式继承 object
3、继承是可以传递的。
参考文档:https://docs.microsoft.com/zh-cn/dotnet/articles/csharp/tutorials/inheritance
来源: http://www.cnblogs.com/simen-tan/p/6763723.html