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

标签 c# inheritance interface polymorphism

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

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

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

class Program
{
    static void Main(string[] args)
    {
        IGrid one = new TextField();
        IGrid two = new SelectList();
        one.Click();
        two.Click();
        Console.WriteLine(one.Text);
        Console.WriteLine(two.Text);
        Console.ReadLine();
    }
}

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

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

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

public class SelectList : Control, IGrid {
    public int Number { get; set; }
    public new string Text {
        get {
            return "Hello Select!";
        }
        set { Number = int.Parse(value); }
    }

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

public class TextField : Control, IGrid {
    public int Number { get; set; }
    public new string Text {
        get {
            return "Hello TextField!";
        }
        set { Number = int.Parse(value); }
        }

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

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

是否有更简洁的方法来解决此类问题,同时又不影响子类的特定属性实现?

非常感谢,

最佳答案

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

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 关键字“隐藏”需要您将接口(interface)转换为特定的类,以便获得该类的实现。

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。您可以只拥有一个 getter 并且只需要实现它。

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

最后,如果你总是要重写一个方法或属性并且永远不会直接创建基类(使用新的)那么你应该考虑使用抽象类如果你有共享实现(例如至少一个方法或您不会更改的属性)或不必理会基类,因为您无论如何都不会使用任何代码。

// 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!");
    }
}

关于c# - 在保持多态性的同时更改子类的属性访问器的适当方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44638210/

相关文章:

c# - 如何保护将由移动应用程序和 Web 使用的 API

c# - 如何在 C# 中调整 Windows 窗体窗体的大小?

java - 为什么子类getter返回其父类(super class)的属性?

vb.net - 如何在 VB.NET 中将接口(interface)属性设置为只读?

与类同名的 Typescript 导入接口(interface)

C# 轮询 TCP 服务器

c# - 具有自定义格式的 XML 编写器

c# - MVC View 继承

inheritance - 何时使用 Dart 中的接口(interface)?

java - 如何在多个不同的对象上调用相同的刻度方法?