代码之家  ›  专栏  ›  技术社区  ›  shsteimer

如何在基类对象上调用子类方法?

  •  4
  • shsteimer  · 技术社区  · 17 年前

    例如:

    SubClassA : BaseClass{
      void Add(ItemA item) {...}
      ItemA CreateNewItem() {...}
    }
    
    SubClassB: BaseClass{
      void Add(ItemB item) {...}
      ItemB CreateNewItem() {...}
    }
    

    不幸的是,基层阶级 。这太好了:

    BaseClass{
      // these aren't actually here, I'm just showing what's missing:
      abstract void Add(ItemBaseClass item);  // not present!
      abstract ItemBaseClass CreateNewItem(); // not present!
    }
    

    不幸的是,由于基类中实际上不存在通用方法,我无法虚拟地调用它们。例如,这将是完美的:

    BaseClass Obj;
    Obj = GetWorkUnit(); // could be SubClassA or SubClassB
    
    ItemBaseClass Item = Obj.CreateNewItem(); // Compile Fail: CreateNewItem() isn't in the base class
    
    Item.DoSomething();
    
    Obj.Add(Item); // Compile Fail: Add(...) isn't in the base class
    

    我如何“强制”调用这些方法?我不担心得到一个不实现我试图调用的方法的对象。我实际上可以在VB中做我想做的事情——我没有智能感知,但编译器很高兴,它工作正常:

    CType(Obj, Object).Add(Item) // Note: I'm using C#--NOT VB
    

    Againt,我无法控制这些类(我认为这排除了部分类)。

    7 回复  |  直到 17 年前
        1
  •  6
  •   Mehrdad Afshari    17 年前

    如果不使用反射或其他肮脏的技巧,就无法调用派生类的非虚方法。如果你想这样做,那很容易:

    // obj is your object reference.
    obj.GetType().InvokeMember("MethodName", 
        System.Reflection.BindingFlags.InvokeMethod, null, obj, null /* args */)
    
        2
  •  3
  •   Lucero    17 年前

    如果你控制着实例的创建过程,你可以通过继承你没有编写的类并添加接口来得到你想要的东西(不需要编写代码,编译器会将接口映射到现有的非虚拟方法)。

        4
  •  0
  •   Lucero    17 年前

        5
  •  0
  •   MStodd    17 年前

    class ItemBase{}
    
    class ItemA : ItemBase{}
    
    class ItemB : ItemBase{}
    
    class BaseClass
    {
        public virtual void Add(ItemBase item){}
        public virtual ItemBase CreateItem() { return null; }
    }
    
    class ClassA : BaseClass
    {
        public override void Add(ItemBase item)
        {
            //do whatever
            throw new NotImplementedException();
        }
    
        public ItemBase CreateItem()
        {
            //create an ItemBase and return
            throw new NotImplementedException();
        }
    }
    
        6
  •  0
  •   Scott Ivey    17 年前

    如果你使用的是Visual Studio 2008,你可以为基类创建一个扩展方法。在该扩展方法中,您将进行强制转换并调用子类的方法。只要您是从VS 2008内部编译的,这也应该适用于以2.0框架为目标的项目。借用其他建议的反射代码,您可以执行以下操作。..

    public static class MyExtensions
    {
       public static ItemBaseClass CreateNewItem(this BaseClass item)
       {
          return item.GetType().InvokeMember("MethodName", System.Reflection.BindingFlags.InvokeMethod, null, obj, null /* args */);
       }
    }
    
        7
  •  -1
  •   Kevin Anderson    17 年前

    您忘记了子类方法定义中的“override”关键字。当某物被声明为“抽象”时,根据定义,它是虚拟的,因此在子类中,你需要在方法声明之前加上“override”关键字。因此,应该采取的措施如下:

    BaseClass{
      abstract void Add(ItemBaseClass item);  // not present!
      abstract ItemBaseClass CreateNewItem(); // not present!
    }
    
    SubClassA : BaseClass{
      override void Add(ItemA item) {...}
      override ItemA CreateNewItem() {...}
    }
    
    SubClassB: BaseClass{
      override void Add(ItemB item) {...}
      override ItemB CreateNewItem() {...}
    }