Oop 面向对象问题:;如果对象是通过基本对象传输的,如何将对象转换为具体对象

Oop 面向对象问题:;如果对象是通过基本对象传输的,如何将对象转换为具体对象,oop,interface,ooad,Oop,Interface,Ooad,我的演示代码如下: class Base { } class SubA:Base { private int propertyA; public int PropertyA { get{return propertyA} } } class SubB:Base { private string propertyB; public string PropertyB {

我的演示代码如下:


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的实例。我想访问“
操作
”中的
属性b
(if
SubB
)或
PropertyA
(if
SubA
)。我是否违反了一些基本的OO规则?处理这种情况的最佳方法是什么(我不想用C#关键字
作为
来测试我转移的对象)。我现在完全糊涂了。非常感谢您提供的任何建议或帮助。

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


问题是您已经定义了
Action
期望接收
Base
作为参数,因此这是您应该依赖的唯一信息。如果类型为
Base
的对象未公开需要公开的数据,则需要对其进行修改。例如,您可以将一个“Property”属性直接添加到base中,并使其成为某种泛型类型,或者添加到具有两个子项的base类型中,一个子项支持
int
值,另一个子项支持
string
值。如果你还可以考虑为什么<代码>动作< /代码>需要访问数据,并且可能将数据的使用委托给<代码> Base< /Cord>及其子代。

< P>可以通过使用类型检查和转换来轻松地绕过技术限制(<代码> A/<代码>和<代码> <代码> >,如您已经看到的,但这确实违反了OO的基本原则


问题是您已经定义了
Action
期望接收
Base
作为参数,因此这是您应该依赖的唯一信息。如果类型为
Base
的对象未公开需要公开的数据,则需要对其进行修改。例如,您可以将一个“Property”属性直接添加到base中,并使其成为某种泛型类型,或者添加到具有两个子项的base类型中,一个子项支持
int
值,另一个子项支持
string
值。如果你也可以考虑为什么<代码>动作< /代码>需要访问数据,并且可能将数据的用法委托给<代码> Base< /Cord>及其子代。

< P>我认为你做的很好,但是,你可能需要通过(Obj[SUB]){}}(Obj:Sub){}来找出OBJ的精确类名。< /P> 根据经验,创建类似void Action(Base obj)的函数的原因是处理obj,而不管它实际上是Base的哪个子类。因此,选择obj作为Base类型意味着您决定不在函数内部执行子类型特定的处理

我在上面的代码中看到,创建超类基类只是为了能够将SubA或SubB传递给Action,而在Action(Base obj)中,似乎您唯一的目的是根据它是SubA还是SubB来处理它。将SubA和SubB作为独立的类而不是继承Base更有意义。然后,您应该为每个SubA和SubB设置单独的操作重载:

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());
    }
}

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

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

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

我在上面的代码中看到,创建超类基类只是为了能够将SubA或SubB传递给Action,而在Action(Base obj)中,似乎您唯一的目的是根据它是SubA还是SubB来处理它。将SubA和SubB作为独立的类而不是继承Base更有意义。然后,您应该为每个SubA和SubB设置单独的操作重载:

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());
    }
}
将调用适当的操作重载。让程序的逻辑决定实例化哪个类。尽可能避免“嗅探”对象的实际类型