[英]Inheritance of auto-implemented property with only getter needed in a derived class
我有下一个代码
class Base
{
public virtual int Prop { get; set; }
}
class Derived : Base
{
public override int Prop { get { return 1; } }
}
//...
Derived obj = new Derived();
int some = obj.Prop; //expected
obj.Prop = 10; //oops it works
乍看之下,最后一行应该符合这一事实似乎并不那么明显。 在我的程序中,我遇到这样的情况:以这种方式覆盖一些自动实现的属性将是一个解决方案。 我知道这不是一个好方法。 为了避免这种继承并清除我的代码,我可以进行哪种重构? 谢谢
class Base
{
public virtual int Prop { get; set; }
}
class Derived : Base
{
public new int Prop { get { return 1; } private set {} }
}
问题在于,如果将“派生为基数”强制转换,则仍然可以设置该属性。 如果将属性中继到某个字段,它将被覆盖。
例如:
class Base
{
protected int fProp;
public virtual int Prop { get { return fProp; } set { fProp = value; } }
}
class Derived : Base
{
public Derived()
{
fProp = 1;
}
public new int Prop { get { return fProp; } private set {} }
}
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
//...
Derived obj = new Derived();
int some = obj.Prop; //expected
Base b = (Base)obj;
b.Prop = 10; //oops it works
Console.WriteLine(obj.Prop); =>it will show 10, not 1
Console.ReadKey();
}
}
}
避免此类问题的“更好”方法是,如果要在派生类上进行“更改”,则避免使用基类。 或者,仅放置所有派生类必须实现的最少内容,并让派生类实现仅他们想要的任何额外代码。
例如:
class Base
{
protected int fProp;
}
class Derived : Base
{
public Derived()
{
fProp = 1;
}
public int Prop { get { return fProp; } }
}
class Derived2 : Base
{
public int Prop { get { return fProp; } set { fProp = value; } }
}
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
//...
Derived obj = new Derived();
int some = obj.Prop; //expected
Base b = (Base)obj;
//obj.Prop = 10; Compilation error
Console.WriteLine(obj.Prop);
Derived2 obj2 = new Derived2();
obj2.Prop = 10;
Console.WriteLine(obj2.Prop);
Console.ReadKey();
}
}
}
另外,您可以“封装”您的基类:
class Derived
{
protected Base fBase;
public Derived()
{
fBase = new Base;
}
//implement enything that you need to access from Base class
public int Prop { get { return 1; } }
}
但是我发现这最后一个太“贵”了... :)
派生类必须实现与其基类相同的接口-使派生类无法访问公共设置器会破坏多态性。
如果Prop需要客户端无法访问,但是您需要能够在类本身内部设置其值,则可以将其声明为:
public virtual int Prop { get; protected set; }
这个问题可能没有一个答案,因为这取决于您特定应用程序的模型。 如果某些派生类需要允许对该属性进行写操作,而另一些不允许,则可以在无效写操作上引发异常并在运行时对其进行处理,或者可以使用受保护的后备字段并且仅使用getter来实现该属性,然后添加一个派生类,该类为需要该类的类提供SetProp()方法。
public class Base
{
protected int prop;
public virtual int Prop { get { return prop; } }
}
public class WriteableBase : Base
{
public virtual void SetProp(int prop) { this.prop = prop; }
}
我认为在这种情况下不可能出现编译器错误。 进一步想象一下,您将obj
声明为Derived
而不是Derived
而是Base = new Derived()
,编译器应如何知道要推断的属性。 因此,您所能做的就是在派生的setter中在运行时抛出一个异常,告诉您此类型不允许设置此属性。
class Base
{
public virtual int Prop { get; protected set; }
}
class Derived : Base
{
public override int Prop {
get { return 1; }
protected set {throw NotSupportedException();}
}
}
编译时,C#将getter和setter转换为单独的方法(get_Prop和set_Prop)。 您的代码仅在Derived类中实现get
,而set
仍保留基类的get
。
如果这是您想要的行为,我认为这不是错误的。
如果要在Derived类中隐藏设置器,则没有优雅的方法,因此抛出NotSupportedException是一种解决方案。
class Base
{
public virtual int Prop { get; set; }
}
class Derived : Base
{
public override int Prop { get { return 1; } set { throw new NotSupportedException();}}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.