【问题标题】:Accessing concrete attributes on abstract object?访问抽象对象的具体属性?
【发布时间】:2011-05-29 09:07:28
【问题描述】:

我猜是一个基本问题,但是如果我希望一个对象拥有另一个类型为 A 或 B 的对象,那么使用该对象的应用程序如何访问特定属性?例如

public abstract class Animal
{
     private int Age;
     // Get Set
}

public class Tiger: Animal
{
     private int NoStripes;
     // Get Set
}

public class Lion : Animal
{
     private bool HasMane;
     // Get Set
}

public class Zoo
{
     private Animal animal;
     // Get Set
}

public static void Main()
{
     Zoo zoo = new Zoo();
     zoo.animal = new Tiger();

     // want to set Tiger.NoStripes
}

【问题讨论】:

    标签: c# inheritance abstract-class derived-class


    【解决方案1】:

    这是继承和多态的要点。

    如果您能够确定 Animal 的实例实际上是 Tiger 的实例,则可以强制转换它:

    ((Tiger)zoo.Animal).NoStripes = 1;
    

    但是,如果您尝试在非 Tiger 的 Animal 实例上执行此操作,您将收到运行时异常。

    例如:

    Zoo zoo = new Zoo();
    zoo.animal = new Tiger();
    ((Tiger)zoo.Animal).NoStripes = 1; //Works Fine
    
    ((Lion)zoo.Animal).NoStripes = 1; //!Boom - The compiler allows this, but at runtime it will fail.
    

    还有一种使用“as”关键字的替代转换语法,如果转换失败,它会返回 null,而不是异常。这听起来不错,但在实践中,当空对象被消耗时,您可能会遇到一些细微的错误。

    Tiger temp = zoo.Animal as Tiger; //This will not throw an exception
    temp.NoStripes = 1; //This however, could throw a null reference exception - harder to debug
    zoo.Animal = temp;
    

    为了避免空引用异常,当然可以空检查

    Tiger temp = zoo.Animal as Tiger; //This will not throw an exception
    if (temp != null)
    {
        temp.NoStripes = 1; //This however, could throw a null reference exception - harder to debug
        zoo.Animal = temp;
    }
    

    【讨论】:

      【解决方案2】:

      直接的答案是做

      public static void Main() {
          Zoo zoo = new Zoo();
          zoo.animal = new Tiger();
      
          ((Tiger)zoo.Animal).NoStripes = 10;
      }
      

      当然,要让它工作,您需要知道zoo.Animal 实际上是Tiger。您可以使用 zoo.Animal is Tiger 进行测试(尽管 as 运算符比 is 更可取)。

      不过,一般来说,这样设计程序并不好闻。您必须编写的代码可能会很麻烦。

      【讨论】:

      • 同意,那么如何解决呢?如果您有一个包含 / 或的对象,例如车库有汽车 A 或汽车 B,那么最佳设计实践是什么?在包含对象中同时创建 A 和 B 似乎也是错误的......
      【解决方案3】:

      您必须将zoo.Animal 转换为Tiger

      或者你可以尝试类似的东西

      public abstract class Animal
      {
          public int Age;
          // Get Set
      }
      
      public class Tiger : Animal
      {
          public int NoStripes;
          // Get Set
      }
      
      public class Lion : Animal
      {
          public bool HasMane;
          // Get Set
      }
      
      public class Zoo<T> where T : Animal
      {
          public T animal;
          // Get Set
      }
      
      Zoo<Tiger> zoo = new Zoo<Tiger>();
      zoo.animal = new Tiger();
      zoo.animal.NoStripes = 1;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多