0

我的演示代码如下:


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(if SubB) 或PropertyA(if SubA) Action。我是否违反了一些基本的 OO 规则?处理这种情况的最佳方法是什么(我不想使用 C# 关键字AsIs测试我转移的 obj)。我现在完全糊涂了。非常感谢任何建议或帮助。

4

2 回答 2

2

as您可以通过使用类型检查和强制转换(以及在 C# 中,正如您已经看到的那样)轻松绕过技术限制is,但这确实违反了基本的 OO 原则。

问题是您已定义Action期望Base作为参数接收,因此这是您应该依赖的唯一信息。如果一个类型的对象Base没有公开你需要它公开的数据,那么你需要修改它。例如,您可以将“Property”属性直接添加到基类,并将其变为某种泛型类型,或者变为具有两个子项的基本类型,一个支持int值,另一个string值。如果您还可以考虑为什么 Action需要访问数据,并可能将这些数据的使用委托给Base它的子代,这可能会有所帮助。

于 2012-12-06T15:01:08.923 回答
1

我认为您所做的很好,但是,您可能需要通过 if (obj is SubA) {} else if (obj is SubB) {} 找出 obj 的确切类名。

根据经验,创建 void Action(Base obj) 之类的函数的原因是为了处理 obj,无论它实际上是 Base 的哪个子类。因此,选择 obj 为 Base 类型意味着您决定不在函数内部进行特定于子类型的处理。

我看到在上面的代码中,创建超类 Base 只是为了能够将 SubA 或 SubB 传递给 Action,而在 Action(Base obj) 中,您的唯一目的似乎是根据它是否处理它子 A 或子 B。让 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());
    }
}

将调用适当的动作重载。让程序的逻辑决定要实例化哪个类。尽可能避免“嗅探”对象的实际类型的需要。

于 2012-12-06T15:01:59.393 回答