• 从设计基类及其派生类看继承关系


    继承能够定义可重用、扩展或修改父类行为的子类。但基类的静态构造函数、实例构造函数和析构函数不能被派生类继承。

     在下面实例中,定义一个基类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

  • 相关阅读:
    Spring入门-对异常的处理
    Spring入门-Interceptor基本使用
    Spring入门-浏览器中文乱码问题
    Spring入门-使用SpringMVC完成一个登陆页面
    Spring入门-获取页面参数&向页面传值&重定向
    【Linux】【NodeJs】Centos7安装node-v10.16.3环境
    【Linux】【Go】Centos7安装go1.13环境
    【Linux】【Fabric】Centos7搭建Fabric运行环境
    【Linux】【ELK】利用elasticproxy对elasticsearch进行二次排序
    【Linux】【ELK】搭建Elasticsearch+Logstash+Kibana+Filebeat日志收集系统
  • 原文地址:https://www.cnblogs.com/simen-tan/p/6763723.html
Copyright © 2020-2023  润新知