如何从Superclass调用两个子类的通用名称方法?

时间:2013-06-28 11:45:24

标签: c# class

在我的日常工作期间,我遇到了一个问题:

假设:

  1. 我们有一个 A 对象,它是Object类型
  2. A 可能会输入B或输入C
  3. 类型BC具有相同的名称方法GetSomething()
  4. 我们不知道BC是否实现了相同的接口(这意味着我们不知道它们之间的关系)
  5. 类型BC继承自Object,这意味着没有任何帮助。除了相同的方法名称,我们对类型BC
  6. 一无所知

    问题是,我想从A打电话给GetSomething,无论它是什么类型:

    //Object A maybe type B or C
    //both B and C can call method
    //but we just don't know type of A
    var result=A.GetSomething();
    

    如果你遇到这种情况,你会做什么?

5 个答案:

答案 0 :(得分:3)

这似乎是一种抽象的方法

public abstract class A {
   protected abstract object GetSomething();
}

在每个派生类中,您需要实现GetSomething(),例如

public class B : A {
   protected override object GetSomeTHing(){
      //implementation goes here
   }
}

然后你可以在超类(GetSomething())的实现中随意调用A

如果你不想在超级类的实现中调用它,但在其他地方你基本上有三个选项

  • 更改超类的实现以包括方法的<潜在抽象)定义
  • 使用动态输入法
  • 使用反射

前者基本上与上面的示例相同(只需设置访问修饰符public而不是protected

第二和第三选择都遭受同样的下行。它们不是键入的编译时间,因此您可能(将)在开发期间偶尔会有运行时错误而不是编译时错误。如果你有一个高测试覆盖率,但不应该是一个问题。

我更喜欢使用动态类型,因为它比反射版更容易阅读和编写。假设GetSomething返回一个int,它看起来像这个

int result =((dynamic)A)。GetSomething();

我将结果更改为显式类型而不是隐式类型,因为否则将其键入为dynamic,导致任何涉及结果的表达式也将被键入动态。如果您知道GetSomething的返回类型,那么最好先告诉编译器

答案 1 :(得分:1)

  
      
  • 类型B和C具有相同的名称方法GetSomething()
  •   
  • 我们不知道B和C是否都实现了相同的接口
  •   

你不知道,但你可以改变吗?因为最合乎逻辑的解决方案是在界面中描述“某事”行为:

interface IHasSomething
{
    Something GetSomething();
}

并将其应用于B和C类。

鉴于您的B和C实例被声明为object,您可以尝试测试它们是否实现此接口:

var something = obj as IHasSomething
if (something != null)
{
    var youWereLookingFor = something.GetSomething();
}

或者你可以尝试使用Reflection,它总是应该是最后的手段而不是优秀的OO设计(如果你想添加参数和/或重载,调用另一种方法,使用不同的返回类型等等)

答案 2 :(得分:0)

如果A没有这种方法,你就不应该考虑这样做,因为这是糟糕的设计和反对OOP原则。但是,如果你绝对必须这样做,你可以尝试使用反射:

MethodInfo methodInfo = this.GetType().GetMethod("GetSomething", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
if(methodInfo != null)
   result = methodInfo.Invoke(this, new object[] {});

但是我强烈建议您在GetSomething()课程中使用抽象类或使用默认A ...

答案 3 :(得分:0)

我能想到的两种方式。直接检查'a'的类型是否实现了预期的类型:

if(a is B)
{
    ((B)a).GetSomething();
}
else if(a is C)
{
    ((C)a).GetSomething();
}

否则,转换为动态,并调用该函数。如果找不到该功能,则会抛出。

dynamic dA = a;
int result;
try
{
    result = dA.GetSomething();
}
catch(RuntimeBinderException ex)
{
    // a was of a type that doesn't have GetSomething
}

第一个例子可以使用,第二个动态示例应该只被视为一个例子,除非它是最后的手段。请尝试使用定义GetSomething()的抽象类或接口。

答案 4 :(得分:0)

在一个好的架构中,您可以通过接口或公共基类访问该方法。

如果您真的想要/需要,那么您要做的就是 duck typing 。您可以使用dynamic关键字或反射。