在保持多态性的同时更改子类的属性访问器的适当方法是什么?

时间:2017-06-19 19:12:23

标签: c# inheritance interface polymorphism

我有一些继承自基类的类,我希望更改属性和方法的实现。我还要求基类和所有子类都是多态的,所以我以后可以创建一个实现特定接口的任何类型的集合。

当我创建实现接口的类的实例时,我想在该类上使用属性和方法(由接口实现),而不是基类。

这是我提供所需输出的问题的简化实现,但确实有代码味道......

cookie: { secure: true }

这有效,但在Control类中有一个空集感觉有点乱。

在不影响子类的特定属性实现的情况下,是否有更清晰的方法解决此类问题?

非常感谢,

1 个答案:

答案 0 :(得分:1)

好的,首先,首先,你不应该在设置属性时更改另一个属性(就像你从文本中的Number那样做)。这是一个巨大的代码味道,因为它是一种副作用。您应该始终直接处理您想要的属性。

public class SelectList : Control, IGrid {
    public int Number { get; set; }
    public new string Text {
        get {
            return "Hello Select!";
        }
        // This is bad, someone after you may not know that this has a side effect
        set { Number = int.Parse(value); }
    }   
}

其次,属性可以像方法一样虚拟,因此将Text属性标记为虚拟属性并在派生类中进行重写将使多态性按预期方式工作。通过new关键字“隐藏”将要求您将接口强制转换为特定类,以便实现类的实现。

public class Control : IGrid
    {
        public virtual string Text
        {
            get { return "Hello Control!"; }

        }

        public virtual void Click()
        {
            Console.WriteLine("In the Control!");
        }
    }
public class SelectList : Control, IGrid
{
    public int Number { get; set; }
    public override string Text
    {
        get
        {
            return "Hello Select!";
        }

    }

    public override void Click()
    {
        Console.WriteLine("In the Select!");
    }
}

第三,您不必在界面上设置setter。你可以只有一个吸气剂,只需要实现它。

public interface IGrid
    {
        string Text { get; }
        void Click();
    }

最后,如果你总是要覆盖一个方法或属性,并且永远不会直接创建基类(使用new)那么你应该考虑使用一个抽象类,如果你有共享实现(EG至少有一个方法或者你没有改变的属性)或者不打扰基类,因为你还没有使用任何代码。

// Abstract class
public abstract class Control : IGrid
{
    // Property that is not overridden but is shared
    public int Number { get; set; }

    public abstract string Text
    {
        get;

    }

    public abstract void Click();
}
public class SelectList : Control
{
    // Don't need the Number property here, base class has it

    public override string Text
    {
        get
        {
            return "Hello Select!";
        }

    }

    public override void Click()
    {
        Console.WriteLine("In the Select!");
    }
}

// Need everything in this class, but if it is all different anyways
//  then base class is kind of a waste
public class TextField : IGrid
{
    public int Number { get; set; }
    public string Text
    {
        get
        {
            return "Hello TextField!";
        }
    }

    public void Click()
    {
        Console.WriteLine("In the TextField!");
    }
}