为什么重新锐化要我不要从抽象类中隐藏属性? 它希望我使用' new',但这总是更可取吗? 这似乎暗示隐藏变量以便用户无法做base.property是一件坏事。
我对这个OO概念感到有些困惑,并且想知道是否有充分的理由支持或反对它。
我有
public abstract class baseClass{
protected string commonProperty {get; set;}
}
public abstract class moreSpecificBaseClass : baseClass {
// Resharper would prefer I use 'new' below
protected string commonProperty = "Some specific setting";
}
public class verySpecificClass : moreSpecificBaseClass {
// Some code
}
答案 0 :(得分:5)
虽然你可以在不使用new修饰符的情况下隐藏成员,但是 结果是一个警告。如果您使用new来显式隐藏成员,那么 抑制此警告并记录派生的事实 版本旨在替代。
隐藏班级成员可能会导致误解和微妙的错误。因此编译器会警告您,并要求您通过使用“new”修饰符使您可能有害成员的意图隐藏。这可以防止意外隐藏基础类型成员而不被忽视。
请参阅这个隐藏成员时问题如何潜入代码的小例子:
public abstract class A
{
public int Value = 0;
}
public class B : A
{
// This hides the Value member from the base type A
public new int Value = 0;
}
static void SetValue(B obj, int value)
{
obj.Value = value;
}
static void AddToValue(A obj, int value)
{
obj.Value += value;
}
static void Main(string[] args)
{
B obj = new B();
SetValue(obj, 11);
AddToValue(obj, 5);
Console.Out.WriteLine("obj.Value = " + obj.Value);
Console.Out.WriteLine("((A) obj).Value = " + ((A) obj).Value);
Console.Out.WriteLine("((B) obj).Value = " + ((B) obj).Value);
}
这将输出:
obj.Value = 11
((A) obj).Value = 5
((B) obj).Value = 11
只需查看 Main 方法的流程,您可能会认为在方法结束时obj.Value的值为16(= 11 + 5)。但事实并非如此 - 更糟糕的是:根据您访问 Value 成员的方式,您将遇到不同的值。
现在,在这个小例子中,输出不相同而不是所有情况下的预期值的原因可能很容易且很快发现。但是想象一下大型软件项目有很多类,有很多继承,方法参数是抽象基类或接口类型,第三方类库,你给它命名......,隐藏成员引起的问题可能变得更加困难识别。
答案 1 :(得分:2)
如果您不希望外部世界能够访问base.property,则应该对其进行保护。如果是,则不应在派生类中重新定义它。如果它根本不可用于派生类,则将其设为私有。
它暗示了新的防止歧义,但实际上你不应该在那里开始。
原因是如果我这样做:
var item = new verySpecificClass();
var val = item.commonProperty;
var basic = (baseClass)item;
if(val == basic.commonProperty)
我会得到与合理程序员所期望的不同的结果。