c#:半抽象自动属性

本文关键字:属性 抽象 | 更新日期: 2023-09-27 17:52:38

在基类中,我想定义一个抽象的get,但此时,我不关心集合。如何在子类中定义setter ?

我试了几样东西,但我不能让它工作。例如:

public class BaseClass
{
    public abstract bool MyBool { get; }
}
public class ChildClass : BaseClass
{
    public override bool MyBool { get; protected set;}
}

:

public class BaseClass
{
    public bool MyBool { abstract get; }
}
public class ChildClass : BaseClass
{
    public bool MyBool { override get; protected set;}
}

我知道我可以通过在子类中不使用自动属性并直接设置底层字段而不是创建setter来解决这个问题,但我正在寻找更好的方法。

Edit:我不想在BaseClass中添加抽象setter

c#:半抽象自动属性

使用接口可能比使用基类更有意义。然后,您只需让需要提供该属性的类实现该接口。

例如,你可以创建这样的接口:

public interface IBoolable {
     bool MyBool { get; }
}

那么像这样实现接口仍然是有效的:

public class BoolableItem : IBoolable {
     public bool MyBool { get; protected set; }
}
这样做,你的代码可以安全地假设任何实现IBoolable的东西都有一个称为MyBool的属性,该属性至少是只读的。

一种解决方案是使MyProperty不是抽象的,而是将其实现委托给一个抽象的受保护的属性,子属性必须覆盖:

public abstract class BaseClass
{
    public bool MyBool { get { return MyBoolInternal; } }
    protected abstract bool MyBoolInternal { get; set; }
}
public class ChildClass : BaseClass
{
    protected override bool MyBoolInternal { get; set; }
}

你必须决定你想要什么行为:如果它被定义为抽象的,那么派生类必须实现它。

那么你应该这样做:

public abstract class BaseClass
{
    public abstract string MyProperty { get; set; }
}

public class DerivedClass : BaseClass
{
    public override string MyProperty
    {
        get { return "myValue"; }
        set { /* do nothing, not applicable for this class */ }
    } 
}

不要抛出NotImplementedException——这不是你想要的,你只是想让setter对一些子类什么都不做。

如果你想在继承的类中使用setter就会违反OOP原则——也就是说,如果一个类(抽象或非抽象)有一个公共/受保护的setter(抽象或非),那么所有继承的类也必须如此;如果一个类没有,那么继承的类也不能。

考虑这个问题的另一种方式是考虑只读或读写属性是类契约的一部分。由于继承类的实例必须遵循"is -a关系"(LSP),继承类不能在主类没有setter的情况下"添加setter",因为主类具有没有作为setter的属性这一事实是主类定义的一部分。实际上,由于主类不能通过setter改变相关属性,因此所有继承类必须保证相同的行为。

考虑使用受保护的后备字段;然后,您可以将此属性拆分为只读属性和单独的setter方法。然后,主类只能拥有该属性,而子类可以拥有主类不知道的setter 方法。但是,我也不确定这是不是一个好的设计。