【问题标题】:How do you override a property with an inherited class? [duplicate]如何用继承的类覆盖属性? [复制]
【发布时间】:2018-08-23 20:22:42
【问题描述】:

代码快速示例

public class BaseSettings {}
public class SpecificSettings : BaseSettings {}
public class BaseClass
{
    public virtual BaseSettings Settings {get; set;}
    public void DoSomething(BaseSettings settings)
    {
        Settings = settings;
    }
}
public class InheritedClass : BaseClass
{
    public override SpecificSettings Settings {get; set;}
}

我有许多继承 BaseClass 的类,它们都将具有相同的“DoSomething”方法。但是,我希望派生类 SpecificSettings 成为调用时设置的类。

如果我使用这个代码,它会产生一个错误告诉我

“InheritedClass.Settings”:类型必须是“BaseSettings”以匹配被覆盖的成员“BaseSettings.Settings”

我不是 OOP 专家,但我认为继承的类 BaseSettings 的一种。

我已经考虑过使用泛型来执行此操作,但它似乎不符合我的要求,因为在某些时候我需要(在反序列化期间)将方法的返回类型设为 BaseClass 类型。

【问题讨论】:

  • 这行不通,因为如果这样做,您将能够执行以下操作:BaseClass obj = new InheritedClass(); obj.Settings = new BaseSettings();。这一定行不通,因为即使 InheritedClass 需要一个 SpecificSettings,您也可以只分配一个 BaseSettings 从而违反类合同。但是,您可以执行以下操作:在 InheritedClass 中定义一个计算机属性,该属性通过编写 public SpecificSettings SpecificSettings { get => (SpecificSettings)Settings; set => Settings = value; } 进行所有转换
  • this post 也可能是一个很好的复制对象
  • 设置和类实现的接口怎么样?这样您就不必重写该属性,只需将其设置为 public ISettings Settings { get; set; }

标签: c# inheritance


【解决方案1】:

BaseClass 类中有一个虚方法

public virtual BaseSettings Settings { get; set; }

如果你的InheritedClass继承到BaseClass并且想要overrideSettings方法,Settings方法签名需要和基类一样。

public class InheritedClass : BaseClass
{
    public override BaseSettings Settings { get; set; }
}

但是你的override 没有意义,因为设置和你的基类做同样的事情。


我会用契约泛型创建接口ISetting<T>,而不是继承BaseClass

您可以使用BaseClassInheritedClass 来实现ISetting<T> 并决定哪个类使用哪个设置。

如果SpecificSettings 扩展了BaseSettings 中的数字属性

我会创建CommonProperty 类来承载属性因为继承使类强耦合。使用组合比继承更灵活。

public class CommonProperty {
    // move your BaseClass common with SpecificSettings in here.
}

public interface ISetting<T>
    where T : BaseSettings
{

    T Settings { get; set; }
    void DoSomething(T settings);
}

public class BaseSettings { }
public class SpecificSettings : BaseSettings { }

public class BaseClass : ISetting<BaseSettings>
{
    public CommonProperty commonProperty { get; set; }

    public virtual BaseSettings Settings { get; set; }
    public void DoSomething(BaseSettings settings)
    {

        Settings = settings;
    }
}
public class InheritedClass : ISetting<SpecificSettings>
{
    public CommonProperty commonProperty { get; set; }
    public SpecificSettings Settings { get; set; }

    public void DoSomething(SpecificSettings settings)
    {
        Settings = settings;
    }
}

【讨论】:

  • 感谢您在回复中付出的努力。问题是我不能使用泛型,因为我需要从函数传回对象,所以它们需要与基类具有相同的类型。我想我想做的事情是不可能的,所以我只是将函数标记为抽象并让继承的类定义它们。
【解决方案2】:

您可以定义一个接口并将其称为 ISetting,BaseSetting 和 SpecificSetting 都实现了该接口。然后,设置的 BaseClass 和 InheritedClass 中的设置类型将为 ISetting Settings。

【讨论】:

  • 一个有趣的想法,我会探索它。然而,现在的问题是,SpecificSettings 扩展了 BaseSettings 中的数字属性。
  • 没关系。让他们都扩展 ISettings。因为当您覆盖方法时,您需要在基类和派生类中具有相同的方法签名。然后将签名更改为 public virtual ISettings Settings {get; set;} 和公共覆盖 ISettings 设置 {get; set;} 然后在派生类中返回一个SpecificSettings的实例。
猜你喜欢
  • 2012-07-11
  • 2014-11-21
  • 1970-01-01
  • 1970-01-01
  • 2013-12-04
  • 2011-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多