【问题标题】:Why does this work? Inheritance为什么这行得通?遗产
【发布时间】:2011-11-20 17:03:03
【问题描述】:

这里没有问题,只需要解释它是如何工作的。

我正在为我的 C# 课做作业,我按照我们教授提供的代码示例设法自己完成了作业。问题是我不明白它是如何工作的。以下是让我感到困惑的事情:

首先,我为什么需要使用xmlBook.Title = "XML Primer Plus";而不是Book clrBook = new Book("CLR via C#", ...")作为构造函数,反之亦然。

二、为什么我在使用: base()的时候不用带参数?

第三,使用new public void display()覆盖,如何只增加输出,而不是完全修改原来的protected void display()?我猜是因为原始的diplay() 受到保护?

请澄清

问候。

Main.cs

using System;

namespace Lab_4
{
    class Program
    {
        static void Main(string[] args)
        {
            Book xmlBook = new Book();
            xmlBook.Title = "XML Primer Plus";
            xmlBook.AuthorFirstName = "Nicolas";
            xmlBook.AuthorLastName = "Chase";
            xmlBook.Price = 44.99F;
            xmlBook.PublisherName = "Sams Publishing";

            Book clrBook = new Book("CLR via C#", 
                                    "Jeffrey", 
                                    "Richter", 
                                    59.99f, 
                                    "Microsoft Press");

            Console.WriteLine("=== xmlBook ===");
            xmlBook.display();
            Console.WriteLine();
            Console.WriteLine("=== clrBook ===");
            clrBook.display();
        }
    }
}

Publication.cs

using System;

namespace Lab_4
{
    public class Publication
    {
        string publisherName, title;
        float price;

        public Publication()
        {
        }

        public Publication(string title, 
                           string publisherName, 
                           float price)
        {
            Title = title;
            PublisherName = publisherName;
            Price = price;
        }

        public float Price
        {
            set
            {
                price = value;
            }
        }

        public string PublisherName
        {
            set
            {
                publisherName = value;
            }
        }

        public string Title
        {
            set
            {
                title = value;
            }
        }

        protected void display()
        {
            Console.Write("{0}\n{1}\n{2}\n", title, publisherName, price);
        }
    }
}

Book.cs

using System;

namespace Lab_4
{
   public class Book : Publication
    {
        string authorFirstName, authorLastName;

        public Book()
        {
        }

        public Book(string bookTitle, 
                    string firstName, 
                    string lastName, 
                    float bookPrice, 
                    string publisherName)
           : base()
        {
            Title = bookTitle;
            AuthorFirstName = firstName;
            AuthorLastName = lastName;
            Price = bookPrice;
            PublisherName = publisherName;
        }

        public string AuthorFirstName
        {
            get
            {
                return authorFirstName;
            }
            set
            {
                authorFirstName = value;
            }
        }

        public string AuthorLastName
        {
            get
            {
                return authorLastName;
            }
            set
            {
                authorLastName = value;
            }
        }

        new public void display()
        {
            base.display();
        Console.WriteLine("{0}", getAuthorName());
        }

        string getAuthorName()
        {
            return AuthorFirstName + " " + AuthorLastName;
        }
    }
}

【问题讨论】:

    标签: c# inheritance constructor


    【解决方案1】:

    1.) 它使用 Book 的构造函数,因此不带参数

    Book xmlBook = new Book();
    

    剩下的只是分配公共属性。

    2.) base() 正在调用基类的构造函数 - 由于 Publication 构造函数没有任何参数,因此您不必(也不能)传递任何参数。请注意,在这种情况下,调用 base() 是可选的,因为基类提供了一个空构造函数。另请参阅"Using Constructors" 作为参考。

    3.) Book 中的display() 方法调用基类的display() 方法作为其实现的一部分,这就是附加输出的原因。请注意,因为方法签名使用new public void,所以Book 类中的方法只有在您通过Book 引用使用时才会被调用,通常您希望使用override

    【讨论】:

    • 你有无数的代表点数,所以我会问你。有什么方法可以使用 ToString 方法输出对象的名称,例如 xmlBook?我试过了,但我失败了。
    • 您的意思是变量本身的名称?通常你想为对象添加一个属性来代表你想要输出的内容。所以添加一个Name 属性。
    • 这是一个代码示例。不使用 ToString,而是使用 Name 属性 abdullin.com/journal/2008/12/13/…
    • 示例对我来说并不是很有吸引力......好吧,而不是这样做: Console.WriteLine("=== xmlBook ===");我可以使用它会自动找到它的名字的东西吗?讲师提供了一些可以取名字的方法,但我不知道这是否相关。
    【解决方案2】:

    1) 使用xmlBook,调用不带参数的构造函数public Book(),然后设置各个字段。

    2) 在带有参数的Books 的构造函数中,您可以使用一些参数调用base,即titlepublisherNameprice。另一种选择(这是您所拥有的)是在 Books 构造函数本身中设置所有字段。

    3) Books.display() 将输出添加到Publication.display(),而不是替换它,因为它调用了base.display()

    【讨论】:

      【解决方案3】:

      第一个问题

      出版物具有公共 Title 属性。书是出版物,所以你可以打电话

      Book xmlBook = new Book();
      xmlBook.Title = "XML Primer Plus";
      

      第二个问题

      Publication 有一个没有任何参数的构造函数。因此,您可以从 Book 类中将其称为 base()。

         public Publication()
          {
          }
      

      第三个问题

      Book 类中的 Display 方法调用 Publication 类中的 Display 方法。请注意,如果您使用new modifier 而不是覆盖,则派生类中的方法不会覆盖基类中的方法,它只是隐藏它。更多信息请查看this thread

      【讨论】:

      • 关于问题 #2,为什么我不能使用非默认构造函数,而是使用它的参数?我花了大约 2 个小时才弄清楚这一点,哈哈。
      • 如果你想调用另一个构造函数,你必须像这样调用 base(bookTitle, publisherName, bookPrice)
      • 是的,你是对的。这样做没有任何意义,因为 Book 类构造函数已经使用其参数设置了 Properties。如果您也可以通过提供这三个参数来提供基类构造函数。它再次尝试设置属性。
      【解决方案4】:

      首先,我为什么需要使用 xmlBook.Title = "XML Primer Plus";而不是 Book clrBook = new Book("CLR via C#", ...") 作为构造函数,反之亦然。

      如果您愿意,可以随意更换它们。任何一个选项都有效,这就是该代码试图演示的内容。

      Book 类有多个构造函数。从类外部的代码(如在您的Main 方法中),您可以调用标记为public 的类的任何构造函数。

      调用new Book(); 时需要设置属性的原因是该构造函数没有设置类的属性。当您调用new Book("CLR via C#", "Jeffrey", "Richter", etc); 时,您正在调用确实设置属性的构造函数。

      第二,为什么我在使用:base()的时候不用带参数?

      基类 (Publication) 也有两个构造函数。当调用base() 时,你调用的是Publication 的不带参数的构造函数。

      当您调用派生类的构造函数时,总会调用基类的某些构造函数。如果没有明确指定要调用哪个基类的构造函数(通过调用base()base("some title", "some publisher name", 0.0f /* some price */)),则默认调用无参数构造函数(即public Publication())。

      第三,使用new public void display()覆盖怎么只增加输出,而不是完全修改原来的protected void display()?我猜是因为原来的 diplay() 被保护了?

      它与受到保护没有任何关系。尝试将其更改为 public,您会看到相同的行为。

      它“添加”行为的方式是在基类中实际调用该函数。 base.display(); 行调用该函数。如果该行不存在,则基类的函数将被有效地“替换”。

      protected 只表示一件事。这意味着你不能从外部代码调用它——你只能从同一个类(Publication)和派生类(Book)内部调用它。 protected 不会“保护”它不被派生类覆盖(使用overridenew)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-04-28
        • 1970-01-01
        • 1970-01-01
        • 2014-12-02
        • 2014-04-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多