我的演示代码如下:
class Base
{
}
class SubA:Base
{
private int propertyA;
public int PropertyA
{
get{return propertyA}
}
}
class SubB:Base
{
private string propertyB;
public string PropertyB
{
get{return propertyB}
}
}
class Program
{
public void Action(Base obj)
{
//here i wanna use PropertyB if the ture obj is an instance of SubB.
// use PropertyA if the true obj is an instance of SubA
}
}
我转移到功能的真实对象" Action
"是SubB或SubA的实例。我想访问" PropertyB
"中的SubB
(如果PropertyA
)或SubA
(如果Action
)。我是否违反了一些基本的OO规则?处理这种情况的最佳方法是什么(我不想使用C#关键字As
和Is
来测试我转移的obj)。我现在完全糊涂了。非常感谢任何建议或帮助。
答案 0 :(得分:2)
您可以通过在C#中使用类型检查和强制转换(as
和is
来轻松绕过技术限制,正如您已经看到的那样),但这确实违反了基本的OO原则。
问题在于您已定义Action
期望接收Base
作为参数,因此这是您应该依赖的唯一信息。如果类型为Base
的对象未公开您需要公开的数据,则需要对其进行修改。例如,您可以将“Property”属性直接添加到base,并将其设置为某种泛型类型,或者添加到具有两个子项的基本类型中,一个支持int
值,另一个string
值。如果你也可以考虑为什么 Action
需要访问数据,并且可能会将该数据的使用权委托给Base
及其子代,这可能会有所帮助。
答案 1 :(得分:1)
我认为你所做的很好,但你可能需要找出obj的精确类名if if(obj是SubA){} else if(obj is SubB){}。
根据经验,创建像void Action(Base obj)这样的函数的原因是处理obj而不管它实际上是什么子类。因此,通过选择obj为Base类型意味着您决定不在函数内部执行特定于子类型的处理。
我在上面的代码中看到,超类Base只能创建为能够将SubA或SubB传递给Action,而在Action(Base obj)中,似乎你的唯一目的是根据它来处理它无论是SubA还是SubB。将SubA和SubB作为不继承Base的单独类更有意义。然后,对于SubA和SubB中的每一个,您应该有一个单独的Action重载:
class Program
{
public void Action(SubA obj)
{
// process exactly as SubA
}
public void Action(SubB obj)
{
// process exactly as SubB
}
}
程序中的其他代码应该构造成知道正在处理哪个SubA或SubB。您可以根据用户输入或条件实例化SubA或SubB。例如:
protected void saveButton_onClick(Object sender, EventArgs e)
{
if (User.IsInRole("Administrator"))
{
Action(new SubA());
}
else
{
Action(new SubB());
}
}
将调用适当的Action重载。让程序的逻辑决定实例化哪个类。避免需要尽可能“嗅探”对象的实际类型。