c#:继承和抽象类 - 基础。 vs:base(在构造函数初始值设定项中)

时间:2017-05-08 19:15:38

标签: c# inheritance constructor abstract

我收到错误:"类型Book'不包含0'的构造函数参数"当我尝试按如下方式设置构造函数时:

using System;
using System.Collections.Generic;
using System.IO;
abstract class Book
{

    protected String title;
    protected  String author;

    public Book(String t,String a){
        title=t;
        author=a;
    }
    public abstract void display();

}

class MyBook : Book
{
    private int price = 0;

    public MyBook(string t, string a, int p)
    {
            base.title = t;
            base.author = a;
            this.price = p;
    }

    public override void display()
    {
        Console.WriteLine($"Title: {title}");
        Console.WriteLine($"Author: {author}");
        Console.WriteLine($"Price: {price}");
    }
}

我已将问题缩小到如何使用base关键字。我应该在其构造函数声明中使用base构造函数初始化器和base关键字。

    public MyBook(string t, string a, int p)
    : base(t, a) 
    {
            this.price = p;
    }

有人请向我解释为什么我不能使用base。在我的构造函数中?是因为标题和作者变量都是抽象类的受保护成员吗?我认为,因为我是从Book中获得的,所以我可以访问这些受保护的成员。或者是因为我没有实例化我的子类,因此我无法以这种方式设置我的构造函数?

4 个答案:

答案 0 :(得分:1)

如果你编写一个没有构造函数的类,编译器会为你定义一个无参数的默认构造函数,以方便编写简单的quickie类。

当您开始显式定义构造函数时,编译器会假定您正在定义您想要的构造函数集。这使您可以控制如何创建类,同时保留编写使用默认构造函数的简单类的便利性。

MyBookBook。在MyBook初始化之前,Book必须首先执行此操作。但是这里没有无参数构造函数。就编译器而言,Book已明确选择禁止您在此处执行的操作。该语言假设如果你想让人 - 子类,你的姨妈莎莉,任何人 - 能够用无参数构造函数创建Book,你就提供了一个。

public MyBook(string t, string a, int p)
{
        base.title = t;
        base.author = a;
        this.price = p;
}

答案 1 :(得分:1)

您可以按照您尝试的方式使用受保护的属性。这不是你遇到的问题。当您尝试创建派生类的实例时,程序需要知道要调用的基类的哪个构造函数来创建该对象的该部分。如果您没有指定,则调用默认(无参数)构造函数。基类没有其中一个,所以你得到错误。 :base(t,a)必须告诉它使用WHICH构造函数,以及传递它的参数。如果你愿意,你可以这样做:

public MyBook(string t, string a, int p)
: base(t, a) 
{
        base.title = t;
        base.author = a;
        this.price = p;
}

当然,在这个愚蠢的例子中,你可以看到它会让你以你尝试的方式使用这些属性。

答案 2 :(得分:0)

您无法在不调用构造函数的情况下设置基类的属性。因为基类有一个带参数的构造函数(并且没有默认构造函数),所以必须显式调用基类的构造函数。

public MyBook(string t, string a, int p)
    :base(t, a)
{
    this.price = p;
}

创建派生类的实例时,实际上是在创建基类的实例。如果一个类具有需要参数的构造函数并且不会具有默认构造函数,那么创建它的唯一方法是调用其中一个构造函数。

如果BookMyBook在同一个程序集中,那么您可以添加一个只有继承类可以调用的protected默认构造函数,如下所示:

protected Book() { }

但要做到这一点,会更好。你把那个构造函数放在那里是有原因的,所以你不需要任何东西"绕过"那个构造函数 - 甚至不是一个继承的类。

例如,您可能认为Book无法使用titleauthor,因此您需要在构造函数中进行验证,以确保它们不是&#39 ; t null。 MyBook调用基类构造函数是件好事,因为现在验证总是发生。

答案 3 :(得分:0)

虽然有多种方法可以解决您的问题。我将尝试以更好的设计视角回答,而不仅仅是解决您的问题。

如果我要定义这样的类结构,我会像这样做

using System;
using System.Collections.Generic;
using System.IO;

abstract class Book
{
    protected String title;
    protected String author;

    public Book(String t, String a)
    {
        this.title = t;
        this.author = a;
    }

    public abstract void display();
}

class MyBook : Book
{
    private int price = 0;

    public MyBook(string t, string a, int p) : base(t, a) // Let the base class decide what it wants to do with these arguments
    {
        this.price = p;
    }

    public override void display()
    {
        Console.WriteLine($"Title: {title}");
        Console.WriteLine($"Author: {author}");
        Console.WriteLine($"Price: {price}");
    }
}