我读过this之类的其他帖子,但它们对我没用。
我有两节课:
public class ClassA
{
public string _shouldBeInteger;
public string _shouldBeBool;
public string _shouldBeDateTime;
}
public class ClassB : ClassA
{
public int? shouldBeInteger
{
get { return (_shouldBeInteger != null) ? Convert.ToInt32(Convert.ToDouble(_shouldBeInteger)) : new int?(); }
set { _shouldBeInteger = Convert.ToString(value); }
}
//... same thing with datetime etc.
}
如果我现在创建一个ClassB的新对象,我得
_shouldBeInteger, _shouldBeBool, _shouldBeDateTime;
shouldBeInteger,shouldBeBool,shouldBeDateTime
但我想隐藏_variables给用户。 在ClassB中将它们设置为私有将覆盖它们,但我需要访问它们才能解析字符串值。
更新
有一个ClassC填充ClassAs'价值观,这主要是他们必须可写的原因。我没办法改变它的工作方式,但我完全控制了ClassA和ClassB
ClassC //not changeAble for me
{
//infomagic filling values of ClassA
}
将ClassA变量设置为私有无法工作,因为ClassA的程序员以一种奇怪的方式生成它。
解决方案
因为ClassA需要是可写的,但除了继承之外不能读取其他类,我终于明白了:
ClassA
{
public string _shouldBeInteger { protected get; set; }
//and so on
}
导致ClassB与theese属性一起使用,而不将它们放在外面。 Intellisense仍会显示它们,但您可以考虑使用:
[EditorBrowsable(EditorBrowsableState.Never)]
解决这个问题。
感谢所有人。
答案 0 :(得分:9)
我认为您可以使用以下方法解决问题:
public class ClassA
{
protected string _shouldBeInteger;
protected string _shouldBeBool;
protected string _shouldBeDateTime;
}
因此派生类可以访问这些变量,但不能访问用户。
用户更新后编辑:
我不知道这对你来说是否适合你,但请尝试:
public class ClassB : ClassA
{
public new int? _shouldBeInteger
{
get { return (base._shouldBeInteger != null) ?
Convert.ToInt32(Convert.ToDouble(base._shouldBeInteger)) :
new int?(); }
set { base._shouldBeInteger = Convert.ToString(value); }
}
}
答案 1 :(得分:4)
继承不能像你想象的那样隐藏成员。 new
修饰符存在以“隐藏”基本成员,但在与基本类型交谈时这不会很好。
http://msdn.microsoft.com/en-us/library/435f1dw2.aspx
您可以更改字段的访问级别(首选方式),也可以包装类而不是继承它,并提供简单的传递方法来委托包装类。这称为Adapter Pattern:
public class ClassB
{
private ClassA _wrappedClass;
}
除此之外,您的公共字段遵循通常用于私有字段的命名约定。
派生类所需的访问级别为protected
。如果成员公开使用但在同一个程序集中,您可以使用protected internal
。如果成员被其他程序集公开使用......我建议重构。
答案 2 :(得分:1)
问题是您在基类中声明了字段public。为了不违反继承的多态性,基类中的任何公共事物也必须在所有派生类中都是公共的。如果你可以改变它,你永远不能确定ClassB可以传递给期望ClassA的东西。
因此,正如其他人所建议的那样,您可能希望将基类字段声明为protected,这类似于私有,除了派生类可以看到它们。
但是,如果您确实需要通过ClassA的实际实例访问它们,则可以将它们声明为private,并为它们提供虚拟公共属性,然后派生类可以覆盖它们。这至少允许派生类改变它们的行为,但它实际上仍然无法隐藏它们。
如果这也不适合,那么可能值得考虑使用组合而不是继承,因为替换原则实际上是妨碍了你的方式,这是继承的基础。
答案 3 :(得分:0)
如果您无法控制ClassA,您需要创建一个包装器/适配器类,如下所示:
public class ClassB
{
private readonly _classA = new ClassA();
public int? shouldBeInteger
{
get
{
return (this._classA._shouldBeInteger != null)
? Convert.ToInt32(Convert.ToDouble(this._classA._shouldBeInteger))
: new int?();
}
set
{
this._classA._shouldBeInteger = Convert.ToString(value);
}
}
}
答案 4 :(得分:0)
public class ClassB
{
private int shouldBeInteger;
public int ShouldBeInteger
{
get { return shouldBeInteger; }
set { shouldBeInteger = value; }
}
}
OR
public class ClassB
{
public int ShouldBeInteger{ get; set; }
}
在这两种情况下,ShouldBeInteger都可以在课堂外访问。
在第一种情况下,有一个私有字段,无法在课堂外访问,
私人领域的价值可以通过公共领域设定。
在第二种情况下,编译器会自动创建一个私有支持字段并执行相同的操作
如上所述的过程。这是自动实现的属性。
希望这可以帮助你。