给出以下内容
class BaseClass
{
public int Property {get; protected set;}
}
class DerivedClass : BaseClass
{
public new int Property {get; set;} //Hides BaseClass.Property
public static DerivedClass Build()
{
var result = new DerivedClass
{
Property = 17;
//base.Property = 17; // this doesn't compile
}
//((BaseClass)result).Property = 17; // this doesn't compile
}
}
有什么方法可以通过DerivedClass内部的静态方法设置BaseClass.Property。
反射或不安全代码不是我想要的!我想要一种简单的方法来设置我们合法有权访问的内容,但是我无法解决设置方法。
答案 0 :(得分:3)
有什么方法可以通过DerivedClass内部的静态方法设置BaseClass.Property。
是的,请重新考虑您的设计。这是有缺陷的。隐藏一个属性,然后想在基类和派生类上设置完全相同的值?似乎确实有问题。
您不一定需要隐藏该属性,可以覆盖它,但是这样做没有太大意义。似乎唯一的目标是在基类和派生类上具有不同的访问修饰符。这违反了OOP规则,应该避免。
答案 1 :(得分:2)
如果可以引入另一个 intermediate 类,那么显然可以做到这一点。但是正如其他人所说的,它不仅具有代码 smell ,而且具有一定的毒性。
class BaseClass
{
public int Property { get; protected set; }
}
class InterClass : BaseClass
{
protected void DoFunnyStuff(int value)
{
this.Property = value;
}
}
class DerivedClass : InterClass
{
public new int Property { get; set; } //Hides BaseClass.Property
public static DerivedClass Build()
{
DerivedClass result = new DerivedClass
{
Property = 17
//base.Property = 17; // this doesn't compile
};
result.DoFunnyStuff(17);
return result;
//((BaseClass)result).Property = 17; // this doesn't compile
}
}
因此DerivedClass
确实仍从BaseClass
继承,但不是直接继承。您可以运用各种技巧来尽量减少InterClass
的存在下暴露出多少其他代码。
答案 2 :(得分:1)
您似乎希望以一种不再可变的方式修改API行为。那么,为什么不定义一个新属性,它实际上是不可变的,而是改用现有的Obsolete
来隐藏原始属性而不隐藏呢?
class LegacyClass
{
[Obsolete("Use NewMember instead")]
public string ExistingMember { get; set; } // should actually be immutable
public string NewMember { get { ... } }
}
这样,您就不会破坏现有的代码。
答案 3 :(得分:1)
以下是从类的静态方法访问重写的属性的方法:
向该类添加访问基本属性的新属性:
private double BaseProperty { get => base.MyProperty; set => base.MyProperty = value; }
使用您的静态文件中的新属性:
var result = new DerivedClass
{
BaseProperty = 17;
}
在这种情况下,上述技术是我发现的最干净的解决方案。
考虑在类库中引用BindableProperty的XAML。
(就我而言,类库是Xamarin Forms。)
在不更改属性名称的情况下,我想将基本属性(由编译到库中的代码使用)与XAML可见属性(在我的子类中)分离。
具体用途是使文本自动适应,这是X-Forms尚不支持的。
这里相关的细节是,我具有以下BindableProperty声明:
public new static readonly BindableProperty FontSizeProperty =
BindableProperty.Create("FontSize", typeof(double), typeof(AutofitLabel), -1.0,
propertyChanged: (BindableObject bindable, object oldValue, object newValue) => {
((AutofitLabel)bindable).BaseFontSize = (double)newValue;
});
使用此私有属性:
private double BaseFontSize { get => base.FontSize; set => base.FontSize = value; }
这完成的工作是首先将base.FontSize设置为XAML中设置的值,该值将由库Label
或其他包含文本的视图中的布局逻辑使用。在子类的其他地方,一旦知道可用的宽度/高度,我就会根据需要降低base.FontSize的逻辑。
这种方法可以在不更改其源代码的情况下使用该库,但对于我的子类的客户端来说,它似乎是内置的自动调整功能。
更改客户端代码可见的FontSize
(代表请求的大小)无效。 However, that is the approach taken by Charles Petzold in XF Book Ch. 5 "EmpiricalFontSizePage"。另外,Petzold的页面本身具有自动调整大小的功能-这并不方便。
面临的挑战是需要告诉图书馆要使用的实际FontSize
。
解决这个问题。
我在网上找到的所有其他方法都需要复杂的自定义渲染器,复制XF库中已经存在的逻辑。
答案 4 :(得分:0)
是的,可以通过反思:Property hiding and reflection (C#)
否,这是不可能的,如果您通过设计隐藏属性,那是因为您不想从DerivedClass授予对该属性的访问权限
Reflection允许您出于特定目的进行访问,这不是使用反射的简单方法。
这是一种访问您已被设计隐藏的属性的黑客方式。
如果您想以合法方式访问财产,则不应将其隐藏。