如何覆盖子类中的字段或属性?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (37)

我有一个抽象基类,我想声明一个字段或一个属性,在每个继承自这个父类的类中都有不同的值。

我想在基类中定义它,以便我可以在基类方法中引用它 - 例如,覆盖ToString以表示“此对象属于类型属性/字段 ”。我有三种方法可以看到这样做,但我想知道 - 做这件事最好的或可接受的方式是什么?新手问题,对不起。

选项1: 使用抽象属性并在继承的类上覆盖它。这受益于执行(您必须重写它)并且它很干净。但是,返回一个硬编码值而不是封装一个字段并且它是几行代码而不是仅仅是一点点代码,感觉有点不对。我还必须声明一个“set”的机构,但这不太重要(并且可能有一种方法可以避免我不知道的)。

abstract class Father
{
    abstract public int MyInt { get; set;}
}

class Son : Father
{
    public override int MyInt
    {
        get { return 1; }
        set { }
    }
}

选项2 我可以声明一个公共字段(或一个受保护的字段),并在继承的类中明确地覆盖它。下面的例子会给我一个使用“新”的警告,我可能会这样做,但它感觉错了,它打破了多态,这是整个点。似乎不是一个好主意......

abstract class Mother
{
    public int MyInt = 0;
}

class Daughter : Mother
{
    public int MyInt = 1;
}

选项3 我可以使用受保护的字段并在构造函数中设置值。这看起来很整洁,但依赖于我,确保构造函数总是设置此值,并使用多个重载的构造函数,总有一些代码路径不会设置值。

abstract class Aunt
{
    protected int MyInt;
}

class Niece : Aunt
{
    public Niece()
    {
        MyInt = 1;
    }
}

这是一个理论性的问题,我想答案必须是选项1,因为它是唯一的安全选项,但是我正在掌握C#并且想要问这些拥有更多经验的人。

提问于
用户回答回答于

在这三种解决方案中,只有选项1多态的

字段本身不能被覆盖。这就是为什么选项2返回 关键字警告的原因。

警告的解决方案不是追加“新”关键字,而是实现选项1。

如果你需要你的领域是多态的,你需要将它包装在一个Property中。

如果您不需要多态行为,选项3是可以的。您应该记住,在运行时访问属性MyInt时,派生类无法控制返回的值。基类本身能够返回这个值。

这就是你的属性真正的多态实现可能看起来如何,从而允许派生类被控制

abstract class Parent
{
    abstract public int MyInt { get; }
}

class Father : Parent
{
    public override int MyInt
    {
        get { /* Apply formula "X" and return a value */ }
    }
}

class Mother : Parent
{
    public override int MyInt
    {
        get { /* Apply formula "Y" and return a value */ }
    }
}
用户回答回答于

选项2是一个非启动器 - 你不能覆盖字段,你只能隐藏它们。

就我个人而言,我会每次选择1。我尽量保持字段在任何时候都是私密的。这就是说,如果你真的需要能够覆盖所有的财产,当然。另一种选择是在基类中具有一个只读属性,该属性由构造函数参数设置:

abstract class Mother
{
    private readonly myInt;
    public int MyInt { get { return myInt; } }

    protected Mother(int myInt)
    {
        this.myInt = myInt;
    }
}

class Daughter : Mother
{
    public Daughter() : base(1)
    {
    }
}

如果这个值在实例的生命周期中没有改变,那么这可能是最合适的方法。

扫码关注云+社区