为某些(但不是全部)继承的类引入setter

时间:2014-05-23 15:45:15

标签: c# .net inheritance properties override

我很难在C#中实现一个在抽象基类中只有 getter 的属性,但我需要在其中一个中引入 setter 派生类。


更新:有关此问题的一般示例的简短说明,see this question。选定的答案解释了为什么目前在C#中无法做到这一点,但是,在我看来还没有提供令人满意的解决方案。


我的班级图概述如下:

Class diagram

我的目标是两个类 TextElementStatic TextElementReferenceSource 应该具有带有getter和setter的 Text 属性,而类 TextElementReferenceTarget 应该只有一个带有getter的 Text 属性。我在引用所有这些对象时不断使用 ITextElement ,我需要确保 ITextElement 界面只有一个getter。此外,基类 TextElement 实现了许多通用代码,因此所有类都需要从该类继承。

我目前的代码如下:

接口:ITextElement

public interface ITextElement
{
    string Text { get; }
}

接口:ITextElementUpdatable

public interface ITextElementUpdatable : ITextElement
{
    new string Text { get; set; }
}

抽象类:TextElement (这是我的问题所在,如下所述)

public abstract class TextElement : ITextElement
{
    // I want to mark this 'abstract', but that causes my problem
    public virtual string Text
    {
        get
        {
            // NOTE: This should never be called
            Debug.Fail("Called virtual Text getter that should never be called");
            return default(string);
        }
    }
}

抽象类:TextElementUpdatable

public abstract class TextElementUpdatable : TextElement, ITextElementUpdatable
{
    // Should have both a getter and a setter  
    public new virtual string Text { get; set; }
}

类:TextElementStatic

public class TextElementStatic : TextElementUpdatable
{
    // Should have both a getter and a setter
    // No Text property declaration
    // Inherits Text property from TextElementUpdatable
}

类:TextElementReferenceSource

public class TextElementReferenceSource : TextElementUpdatable
{      
    // Should have both a getter and a setter     
    public override string Text
    {
        get { return _internalobject.Text; }
        set { _internalobject.Text = value; }
    }
}

类:TextElementReferenceTarget

public class TextElementReferenceTarget : TextElement
{
    // Should ONLY have a getter
    public override string Text
    {
        get { return _internalobject.Text; }
    }
}

所以,我的问题是:我真的想在基类TextElement抽象中声明Text属性,因为它应该始终在派生类中实现(TextElementUpdatable,TextElementReferenceSource和TextElementReferenceTarget都实现了这个属性)。但是,如果我尝试将该属性转换为public abstract string Text { get; },那么我会在 TextElementUpdatable 中收到错误,指明

TextElementUpdatable.Text hides the inherited property TextElement.Text

此外,如果我将 TextElementUpdatable 中的属性从new更改为override,则错误消息将替换为:

Cannot override because TextElement.Text does not have an overridable set accessor

现在,我可以回到 TextElement 并将属性更改为public virtual string Text { get; private set; }并将其调用一天,因为无论如何都不应该调用该方法(这基本上就是我所拥有的解决方案)现在)。但是,如果我或某人稍后创建了另一个派生类,我想强迫我/他们实现Text-property,因此我宁愿将其标记为抽象而不是提供虚拟实现。

关于如何以正确的方式做到这一点的任何建议 - 即使它应该涉及大量的重构?

我知道我可以将她的两个目标分开,只提供一个继承的 Text 属性,只有一个getter,然后在 ITextElementUpdatable SetText()方法>界面。但是,我想知道是否有可能找到一个只有属性的好解决方案。


另一个类似的问题,但没有任何答案,我已经能够使用:C# - What should I do when every inherited class needs getter from base class, but setter only for ONE inherited class

2 个答案:

答案 0 :(得分:1)

这真是一个令人兴奋的设计问题,但是..你必须使用新的关键字,这不是一个好的做法。尽量避免它们。 当然,接口中的属性名称可以是相同的,但如果两者都是由类(以及没有setter定义的一个props)实现的,我们必须实现它们。我们必须接受这些属性"冲突"。 你可以介绍抽象方法:

public abstract class TextElement : ITextElement
{
    public string Text { get { return GetText(); } }

    protected abstract string GetText();
}

public abstract class TextElementUpdatable : TextElement, ITextElementUpdatable
{
    string ITextElementUpdatable.Text
    {
        get { return GetText(); }
        set { SetText(value); }
    }

    protected abstract void SetText(string text);
}

答案 1 :(得分:0)

在层次结构中使用具有不同含义的相同属性可能有点令人困惑。也许ITextElement.get_Text和ITextElementUpdatable.get_Text的实现稍后会分歧 - 接口定义了两个独立的行为,我们不会一直使用基本类型,比如string。 所以我的建议是你应该在ITextElement中有一个属性用于只读目的,而ITextElementUpdatable中的另一个属性具有不同的名称。通过这种方式,您的方法当然可以定义为抽象的。