【问题标题】:Calling subclass constructors from the base constructor in C#从 C# 中的基构造函数调用子类构造函数
【发布时间】:2018-05-25 04:31:41
【问题描述】:

我想从基类构造函数调用子类构造函数,并将创建的子类对象作为基类对象。 代码如下所示。

class Text
{
    public string OriginalText;

    public Text() { }

    public Text(string text)
    {
        OriginalText = text;
        text = FormatText(text); // like text.ToUpper().Trim()

        if (Category1.Check(text))
            new Category1(text);
        else if (Category2.Check(text))
            new Category2(text);
        else if (Category3.Check(text))
            new Category3(text);
    }

}

class Category1 : Text
{
    public string Property1;
    public Category1(string text)
    {
        Property1 = text + "#1";
    }

    static public bool Check(string text)
    {
        return text == "category1";
    }
}

class Category2 : Text
{
    public string Property2;
    public Category2(string text)
    {
        Property2 = text + "(2)";
    }

    static public bool Check(string text)
    {
        return text == "category2";
    }
}

class Category3 : Text
{
    public string Property3;
    public Category3(string text)
    {
        Property3 = text + "%3";
    }

    static public bool Check(string text)
    {
        return text == "category3";
    }
}

但是,var t = new Text("category1") 不是子类的对象。我通过评估t is Category1 来检查它,它是false。我尝试添加 returnnew Category1(text) 前面,但由于构造函数返回 void 类型,这种方法失败了。以下是日文翻译的错误信息。

An object statement can't be used after the keyword return since MainWindow.Text.Text(string)' returns void type

解决此问题的一种方法是定义一个返回子类对象的静态方法。

static public Text GetCategory(string text)
{
    text = FormatText(text);
    if (Category1.Check(text))
        return new Category1(text);
    else if (Category2.Check(text))
        return new Category2(text);
    else if (Category3.Check(text))
        return new Category3(text);
    return null;
} 

但是,这一次,OriginalText = text; 不能使用,因为这是一个静态方法。我承认可以通过将以下代码添加到每个

if 语句的内容之一

string tmp1 = text;
text = FormatText(text);
var c1 = new Category1(text); 
c1.OriginalText = tmp1;
return c1;

或在每个子类构造函数中设置OriginalText

但这会使代码冗长、冗余且难以阅读和维护。我想在同一个地方聚合常用进程,我的意思是,基础构造函数。

谷歌搜索“调用子类构造函数 c#”给了我 2 篇文章,这对我来说不是答案。

  1. Calling subclass constructor from static base class method
    这是无关紧要的。这是关于调用从基类继承的静态子类方法。

  2. How to call subclass constructor only in inheritence
    这是不同的。这个是关于调用子类构造函数而不调用基类构造函数的。

我该如何处理这个问题?

【问题讨论】:

  • “我想从基类构造函数中调用子类构造函数,并将创建的子类对象作为基类对象。”没有“基类对象”这样的东西。只创建了一个对象,并且它的类型从一开始就正确。看起来你真正想要的是一个静态工厂方法。
  • "OriginalText = text; 不能使用,因为这是一个静态方法" - 当然可以。这是public。不要在同一行使用returnnew,而是使用不同的代码行。创建您的new 对象,在该对象上设置您的值,然后返回该对象。您无法在this 上设置该值,但这不是您想要 设置它的地方。您想在返回的对象实例上设置它。

标签: c# inheritance constructor subclass base-class


【解决方案1】:

在您所说的代码块中,您正在创建一个新实例,但它从未分配给变量,也不能从构造函数返回:

if (Category1.Check(text))
    new Category1(text); // <-- wrong!

构造函数是一种为给定类型初始化内存中新创建空间的方法。您不能从构造函数中更改类型!

您想要一个工厂模式,就像您在第二个示例中给出的那样。这是您最好也是唯一的选择:

static public Text GetCategory(string text)
{
    text = FormatText(text);
    if (Category1.Check(text))
        return new Category1(text);

【讨论】:

    【解决方案2】:

    正如 Patrick 正确解释的那样,您想使用工厂模式。 关于OriginalText,您不必重复此代码。只需像这样创建您的工厂方法:

    static public Text GetCategory(string text)
    {
        var formattedText = FormatText(text);
        Text result = null;
        if (Category1.Check(formattedText))
            result = new Category1(formattedText);
        else if (Category2.Check(formattedText))
            result = new Category2(formattedText);
        else if (Category3.Check(formattedText))
            result = new Category3(formattedText);
        if(result != null)
            result.OriginalText = text;
        return result;
    } 
    

    【讨论】:

      猜你喜欢
      • 2014-02-19
      • 2015-08-18
      • 1970-01-01
      • 1970-01-01
      • 2016-07-19
      • 2018-07-21
      • 2013-03-24
      • 1970-01-01
      • 2020-11-28
      相关资源
      最近更新 更多