繼承可以定義可重用、擴展或修改父類行爲的子類。但基類的靜態構造函數、實例構造函數和析構函數不能被派生類繼承。ide
在下面實例中,定義一個基類Publication用於表示任何類型的出版物以及派生至Publication的其餘類型Book類,由此也能夠擴展爲定義其餘類型如:Magazine、Journal、Newspaper和Article。函數
在設計基類Publication時咱們必須考慮到以下關係:ui
1.要在基類中添加哪些成員this
2.基類是否用做派生類模板的抽象基類spa
3.類層次結構的擴展空間大小,要開發包含三個或多個的類的層次結構,如Publication是Periodical的基類,又能夠是Magazine和Journal的基類設計
4.可否重寫基類實現的代碼,若是允許重寫,必須在基類中使用關鍵字virtual,派生類才能容許重寫基類方法。code
5.派生類是否必須繼承結構的終結類,且自己不被用做其餘派生類的基類,這時能夠用sealed 關鍵字來標識該類blog
先定義一個出版物類型的枚舉繼承
public enum PublicationType:long { [Description("報紙")] Newspaper=1, [Description("雜誌")] Magazine =2, [Description("書籍")] Book=3 }
再定義Publication抽象基類ip
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 void Main(string[] args) { var tPublication = typeof(Publication); var tBook = typeof(Book); var flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; var membersPublication = tPublication.GetMembers(flags); var membersBook = 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 (var member in members) { var access = string.Empty; var stat = string.Empty; if (member is 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"; } var output = $"{member.Name} ({member.MemberType}): {access}{stat}, Declared by {member.DeclaringType}"; Console.WriteLine(output); } }
從輸出結果分析可得出:
一、Publication 和Book都隱式繼承自基類
二、派生類只能有一個一個直接基類,固然能夠隱式繼承object
三、繼承是能夠傳遞的。
參考文檔:https://docs.microsoft.com/zh-cn/dotnet/articles/csharp/tutorials/inheritance