【问题标题】:Declaring a variable of an abstract class type声明一个抽象类类型的变量
【发布时间】:2012-06-21 09:30:37
【问题描述】:

我有一个带有一些受保护成员的抽象基类,但没有抽象成员:

internal abstract class BaseClass
{

    protected readonly string Var1;
    protected readonly string Var2;

    protected BaseClass(string var1, string var2)
    {
        Var1 = var1;
        Var2 = var2;
    }

    protected int DoSomething1(string s)
    {
    }
}

还有一些类实现了这个基类,并且每个类都有一些不同的特定方法:

internal sealed class Child1:BaseClass
{
    internal Child1(string var1, string var2)
        : base(var1, var2)
    {
    }

    internal bool DomeSomethingSpecificForChild1(int i)
    {
    }

}

现在我有另一个类,我想有一个BaseClass 类型的变量,并根据我的需要,用一个子类型来实例化它。 但这不起作用,因为具体方法未知。

public class MyClass
{
        private BaseClass myBaseClass;

    public bool DomeSomethingSpecific(int i)
    {
            myBaseClass = new Child1("a","b");
            myBaseClass.DomeSomethingSpecificForChild1(i);
    }
}

有什么方法可以实现我想要的吗? 还是我必须在MyClass 方法的内部范围内声明我的变量?

public class MyClass
{
        private BaseClass myBaseClass;

    public bool DomeSomethingSpecific(int i)
    {
            var child1 = new Child1("a","b");
            myBaseClass.DomeSomethingSpecificForChild1(i);
    }
}

但是这样我不确定该类是否实现了BaseClass

接口不是一个选项,因为我希望它保持内部,而不是公开, 而且我不希望基类被实例化,所以我认为抽象在这里是一个不错的选择..

【问题讨论】:

  • 您的代码不会按原样运行,您必须在子类中标记要覆盖的函数 virtual,在子类中定义函数时还需要使用“override”关键字
  • @MSUH 我知道,但问题是我不想覆盖任何方法。我已经将每个类的相同方法作为基类中的受保护方法。在 childclass 中,我可以放任何我喜欢的东西。我只是想确保我在“MyClass”中实例化的类确实实现了“BaseClass”。
  • 那你需要检查 if (child1 is BaseClass){child1.DomeSomethingSpecificForChild1(1);}
  • 恐怕你是对的。也许我必须寻找不同的设置,因为这不是我想要的......无论如何,谢谢。

标签: c# abstract-class


【解决方案1】:
private BaseClass child;

public bool DomeSomethingSpecific(int i)
{
        var c = {initialization to an instance - e.g. Child1(), Child2(), Child3()..};
        if (c is Child1){
            ((Child1)c).DomeSomethingSpecificForChild1(i);
        }
}

【讨论】:

    【解决方案2】:

    您可能喜欢使用抽象方法:

    internal abstract class BaseClass
    {
    
        protected readonly string Var1;
        protected readonly string Var2;
    
        protected BaseClass(string var1, string var2)
        {
            Var1 = var1;
            Var2 = var2;
        }
    
        protected int DoSomething1(string s)
        {
        }
    
        public abstract bool DoSomethingSpecific(int i);
    }
    

    然后

    internal sealed class Child1:BaseClass
    {
        internal Child1(string var1, string var2)
            : base(var1, var2)
        {
        }
    
        public override bool DomeSomethingSpecific(int i)
        {
        }
    
    }
    

    【讨论】:

    • 也想过这个,但是每个孩子的名字和方法的数量都不一样,所以不能把它们抽象化。
    • @Koen 这不是一个好主意,因为如果您为每个名称设置不同的名称,您将需要一堆 if 来尝试转换为所有这些类型来决定调用什么。为什么名字那么重要?
    • 因为它有不同的功能。相同的成员是基类中的受保护成员。子类中的其余部分可以是任何东西。我只是想要“MyClass”中的一些结构来强制我在那里使用的类应该实现 BaseClass。
    【解决方案3】:

    将子类对象转换为基类

    public class MyClass
    {
        public bool DomeSomethingSpecific(int i)
        {
                var child1 = new Child1("a","b");
                ((myBaseClass)child1).DomeSomethingSpecificForChild1(i);
        }
    }
    

    【讨论】:

      【解决方案4】:

      显然,将变量声明为基类实例,您只能使用基类公开的方法。

      要使用特定的类方法,您需要强制转换对象,所以:

      if(child is Child1)
      {
          Child1 c1 = child as Child1
          if(c1 != null) c1.specificMethod1();
      }
      if(child is Child2)
      {
          Child2 c2 = child as Child2
          if(c2 != null) c2.specificMethod2();
      }
      // ...
      

      【讨论】:

        猜你喜欢
        • 2012-07-23
        • 1970-01-01
        • 2021-12-07
        • 2010-10-23
        • 2016-05-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-30
        相关资源
        最近更新 更多