创建摘要 类,其中包含要从 children 中使用的常用方法

Create abstract classes that contain common methods to be used from their children

我想做的是创建抽象 classes,其中包含要从他们的 children 使用的常用方法。因为我需要 children 的静态实例引用,所以我正在做类似

的事情
public abstract class Environment<T> where T : Environment<T> {

  private static T s_instance;

  public static T Instance {
    get {
      return (T)s_instance
    }
  }  
}

这样,如果我将在 child 上调用实例 属性,我将获得 child 实例,而不是将 child 声明为的抽象实例:

public Desert : Environment<Desert> { }

所以如果我这样做

Desert.Instance

我将获得 Desert 实例及其所有实现和新方法(以及在基础中定义的方法)。
假设我有 2 个这样的 class:环境和动物。
假设我有 2 个环境的沙漠和丛林。
假设我有蝎子和狮子,它们是 2 种动物。

我想做的是从 Environment 访问 Animal class 的一些属性,但对它的实现一无所知。

非常愚蠢的例子:

  1. 我将实例化一个沙漠(一次只存在一个环境)
  2. 沙漠将有一个动物预制件列表,可以实例化以匹配那里允许的物种
  3. 一旦它被实例化,如果没有那种动物已经存在,自动实例化 1 个(例如蝎子)并且只实例化一个动物,这样我就可以用静态实例 属性 引用它。在实例化的动物被销毁之前,不会实例化其他动物。

第一个问题是,在环境中,我需要一个定义为动物列表的列表(数组、字典、通用列表......等等),然后,沙漠职责来填充它与 Scorpion 和其他人一起列出。显然我不能用通用类型定义结构:

protected List<Animal<T>> animalsList = new List<Animal<T>> ();


另一件事是:看到在空环境中实例化通用动物的动作很常见,我希望我的通用环境可以检查动物是否已经实例化,如果没有,则实例化一个。问题是因为 Animal 是通用的,所以我做不到

if (Animal.Instance == null) {
   Instantiate (animalList[Random(0, animalList.Length)]);
}

(请注意,以上为伪代码)

我希望我没有太混乱。也许这是错误的整个想法,也许我不能有泛型,但如果您有任何建议,我们非常欢迎。 谢谢大家 :-)


编辑: 为什么要使用泛型???
因为我试图用通用操作创建一个基础 class 并且因为我需要对 children 实例的静态引用,所以我将基础 classes 定义为通用的。同样,如果我这样做,实例 属性 需要在基础 class 中声明,但如果它被 children 调用,它将返回 children实例.
示例:

public abstract class Environment<T> where T : Environment<T> {

  private static T s_instance;

  public static T Instance {
    get {
      return (T)s_instance
    }
  }

  public int CommonMethod () {
     return 1;
  }
}

public class Desert : Environment<Desert> {

   public int SandStorm () {
      return 12;
   }
}

public class Jungle : Environment<Desert> {

   public int Rain () {
      return 200;
   }
}

在我的控制器中我可以做到

public class Controller () {

   public void CallCommonMethod () {
      Console.Write (Desert.Instance.CommonMethod ());
      Console.Write (Jungle.Instance.CommonMethod ());
   }

   public void CallSandStorm () {
      Console.Write (Desert.Instance.SandStorm ());
   }

   public void CallRain () {
      Console.Write (Jungle.Instance.Rain ());
   }
}

在这种情况下不允许这样做

public class Controller () {

   public void CallCommonMethod () {
      Environment.Instance.CommonMethod ();
      // or
      Environment<T>.Instance.CommonMethod ();
      // or similar
   }
}

如果我有

public abstract class Environment {

  public int CommonMethod () {
     return 1;
  }
}

public class Desert : Environment {

   public Desert Instance { get; private set; }

   public Desert () {
      Instance = this;
   }       

   public int SandStorm () {
      return 12;
   }
}

public class Jungle : Environment {

   public Jungle Instance { get; private set; }

   public Jungle () {
      Instance = this;
   }       

   public int Rain () {
      return 200;
   }
}

我需要为每个 children 定义实例。可能我很懒,但我认为通用的方式会更好。

这里有很多问题,但首先要了解泛型类型的协变和逆变:

Return an inherited type from a method

这是一个很常见的问题。这是我最近回答的 link。

对于你懒惰的问题,你可以这样做

public abstract class Environment
{
    private static Environment instance;

    public static T GetInstance<T>() where T : Environment
    {
        return (T)instance;
    }
}

public class Desert : Environment
{

}

public class class1
{
    public void SomeMethod()
    {
        Environment.GetInstance<Desert>()
    }
}

您只需添加代码以在抽象泛型基础中创建实例 class。

public abstract class Environment<T> where T : Environment<T>, new()
{
    private static T _instance = new T();
    public static T Instance
    {
        get { return _instance; } // no need to cast here. It's already of type T.
    }

    public int CommonMethod()
    {
        return 1;
    }
}

public class Desert : Environment<Desert>
{
    public int SandStorm()
    {
        return 12;
    }
}

那么用法就如你所愿。 Desert.Instance.SandStorm()Desert.Instance.CommonMethod().

评论中关于使用工厂的建议 and/or 摆脱单身要求可能是有效的,但您已经非常接近您正在寻找的东西。

编辑:

您也可以像这样访问静态 Instance 属性:

Environment<Desert>.Instance.CommonMethod();
Environment<Desert>.Instance.SandStorm();

但是在指定通用类型之前,您无法获得 Instance。所以 Environment.Instance 不可用。

为了完整起见,这是我的最终解决方案。请注意,某些部分是伪代码。这只是为了让您了解我的想法。

public abstract class Environment<T> where T : Environment<T> {

   private List<Animal> animalList;
   private static T s_instance;

   public static T Instance {
      get {
         return (T)s_instance
      }
   }

   public void ToCallInConstructor () {
      PopulateTheList ();
      if (Animal.Instance == null) {
         Instantiate (animalList.Get (defaultAnimal)); // pseudocode
      }
   }

   public int CommonMethod () {
      return 1;
   }

   public abstract void PopulateTheList();
}

public abstract class Animal {

   public static Animal Instance { get; private set; }

   public Animal () {
      Instance = this;
   }

    public static T GetInstance<T>() where T : Animal {
       return (T)Instance;
    }
}

其他一切都将遵循我在问题的编辑部分中所做的示例,我在其中解释了为什么使用泛型。

非常感谢大家的建议,尤其是Patrick和CoderDennis。 :-)