我有几个继承自基类的类,我希望为其更改属性和方法的实现。我还要求基类和所有子类都是多态的,这样我以后可以创建一个实现特定接口(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/