从设计基类及其派生类看继承关系
2017-04-27 21:54
120 查看
继承能够定义可重用、扩展或修改父类行为的子类。但基类的静态构造函数、实例构造函数和析构函数不能被派生类继承。
在下面实例中,定义一个基类Publication用于表示任何类型的出版物以及派生至Publication的其他类型Book类,由此也可以扩展为定义其他类型如:Magazine、Journal、Newspaper和Article。
在设计基类Publication时我们必须考虑到如下关系:
1.要在基类中添加哪些成员
2.基类是否用作派生类模板的抽象基类
3.类层次结构的扩展空间大小,要开发包含三个或多个的类的层次结构,如Publication是Periodical的基类,又可以是Magazine和Journal的基类
4.能否重写基类实现的代码,如果容许重写,必须在基类中使用关键字virtual,派生类才能允许重写基类方法。
5.派生类是否必须继承结构的终结类,且本身不被用作其他派生类的基类,这时可以用sealed 关键字来标识该类
先定义一个出版物类型的枚举
再定义Publication抽象基类
Book表示一种类型的出版物,继承至Publication
在代码图中查看Book和Publication类的依赖关系和类中成员的引用关系
使用反射分别获取Book和Publication类的成员列表
从输出结果分析可得出:
1、Publication 和Book都隐式继承自基类
2、派生类只能有一个一个直接基类,当然可以隐式继承object
3、继承是可以传递的。
参考文档:https://docs.microsoft.com/zh-cn/dotnet/articles/csharp/tutorials/inheritance
在下面实例中,定义一个基类Publication用于表示任何类型的出版物以及派生至Publication的其他类型Book类,由此也可以扩展为定义其他类型如:Magazine、Journal、Newspaper和Article。
在设计基类Publication时我们必须考虑到如下关系:
1.要在基类中添加哪些成员
2.基类是否用作派生类模板的抽象基类
3.类层次结构的扩展空间大小,要开发包含三个或多个的类的层次结构,如Publication是Periodical的基类,又可以是Magazine和Journal的基类
4.能否重写基类实现的代码,如果容许重写,必须在基类中使用关键字virtual,派生类才能允许重写基类方法。
5.派生类是否必须继承结构的终结类,且本身不被用作其他派生类的基类,这时可以用sealed 关键字来标识该类
先定义一个出版物类型的枚举
public enum PublicationType: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 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); } }
从输出结果分析可得出:
1、Publication 和Book都隐式继承自基类
2、派生类只能有一个一个直接基类,当然可以隐式继承object
3、继承是可以传递的。
参考文档:https://docs.microsoft.com/zh-cn/dotnet/articles/csharp/tutorials/inheritance
相关文章推荐
- 二十七、继承(四) 多重继承、虚继承与虚基类、虚基类及其派生类构造函数
- 【c++】深入剖析虚拟继承与各种继承关系中派生类内成员内存分布情况及虚基类表的内容
- 继承与派生:虚基类及其派生类的构造函数
- 重构 — 改善既有的类图设计 条款8:消除继承类和基类中重复的依赖关系
- C++-继承:基类与派生类的关系
- c++派生类转换为基类与public、protected、private继承的关系
- 派生类和基类的关系—类继承
- C++-继承:基类与派生类对象的关系&&继承与组合
- 四十二、继承与派生:虚基类及其派生类的构造函数
- 鸡啄米:C++编程入门系列之四十二(继承与派生:虚基类及其派生类的构造函数)
- 友元关系与继承以及基类派生类定义构造函数时应该注意的事项
- C++编程入门系列之四十二(继承与派生:虚基类及其派生类的构造函数)
- 派生类不继承基类的static成员
- C++ 学习之继承1:基类与派生类
- 抽象类与接口及其派生类的关系
- 【提问整理】protected继承,派生类对象如何访问基类成员?
- 虚拟单一继承下基类和派生类起始地址不同
- C++编译器:虚基类及其派生类的构造函数
- 鸡啄米:C++编程入门系列之三十七(继承与派生:派生类对基类成员的访问控制之公有继承)
- 关于基类派生类的继承访问权限