【问题标题】:Create instance of interface child class创建接口子类的实例
【发布时间】:2016-11-23 09:17:46
【问题描述】:

我有接口和派生它的 3 个类,但是如何为每种类型使用 1 个变量?

  public interface IBuilder<T> where T: System.IConvertible{}

  public class SimpleBuilder :  IBuilder<SimpleCollagePatterns>{}

  public class CreativeBuilder : IBuilder<CreativeCollagePatterns>{}

  public class ShapeBuilder : IBuilder<ShapeCollagePatterns>{}

而且我需要在必要时创建类的实例

我有 IBuilder&lt;IConvertible&gt; currentBuilder 变量,但我无法创建任何 Builder 的实例

this.currentBuilder = new SimpleBuilder(); //Doesn`t work

只有当我将 IBuilder&lt;IConvertible&gt; currentBuilder 更改为 IBuilder&lt;SimpleCollagePatterns&gt; currentBuilder 或其他类型时,我才能创建这种类型的 Builder,但我需要让 ability 创建任何类型

【问题讨论】:

  • 接口不是类,所以你不能创建它们的实例。创建实例的唯一方法是您选择的方式,即定义实现接口的类,例如简单拼贴图案。此外,接口不包含任何执行特定操作的代码,那么您为什么要创建它们的实例呢?为什么不将 IBuilder 更改为父类?
  • 你面临的问题是你有I&lt;T1&gt;I&lt;T2&gt;(即同一个泛型接口使用了两次不同的泛型参数),并且T1之间存在继承层次结构和T2。问题是I&lt;T1&gt;I&lt;T2&gt; 之间没有继承层次结构。您可以根据继承的方式使用协变和逆变来处理此问题,但这对类型的使用施加了非常具体的限制,可能不是您想要的。简而言之,这是不可能的。

标签: c# windows


【解决方案1】:

我遇到了同样的情况。但最终发现没有解决方案。无法在运行时创建任何类型的对象。正如您所说,将 IBuilder currentBuilder 更改为 IBuilder currentBuilder 是为 SimpleBuilder 类型创建对象的唯一方法。其他情况类似。

【讨论】:

  • 我还有另一种使用 dynamic 类型 currentBuilder 的方法,但效果不好
  • 是的。这不好。所以解决方案是为每种类型设置一个单独的对象。
【解决方案2】:

如果你真的想在所有场景中使用一个变量,你总是可以将它定义为一个简单的对象来保存实例,并在必要时使用 IS 运算符查看它到底是哪种类型:

如果(this.currentBuilder 是 SimpleBuilder) { }

【讨论】:

  • 但我无法更改它。我需要改变类型
  • 为什么不能更改currentBuilder的声明?这不是你自己的代码吗?所以将 IBuilder currentBuilder 替换为 object currentBuilder.
  • 怎么做?
  • 替换 IBuilder currentBuilder 为对象 currentBuilder
  • 嗯,我尝试过,但总是在我使用它时,我需要强制转换为必要的类型?
【解决方案3】:

我相信您需要使您的 IBuilder 协变,请参阅 https://msdn.microsoft.com/en-us/library/dd997386(v=vs.110).aspx

public interface IBuilder&lt;out T&gt;

【讨论】:

    【解决方案4】:

    您要阅读的内容称为协方差,在接口声明中的泛型类型参数旁边用关键字out 表示。

    public interface IBuilder<out T> where T: System.IConvertible{}
    

    这将允许您声明IBuilder&lt;IConvertible&gt; 类型的变量并分配例如。 SimpleBuilder 对于它,你只需要知道应用协方差的后果是什么,最重要的是,通俗地说,泛型类型只能用作类型成员的返回类型。

    如果您无法更改 IBuilder 接口 - 没有为所有情况创建变量的选项。

    有关更多信息,您可以研究 SO,例如。 Difference between Covariance & Contra-variance 或阅读源代码,例如。 https://msdn.microsoft.com/en-us/library/mt654055.aspx.

    【讨论】:

      【解决方案5】:

      如果您不需要公开访问泛型类型

      特别是如果SimpleCollagePatterns 被实现该特定接口的类(在本例中为ShapeBuilder)独占使用,那么您不需要协方差

      有一种简单的设计模式,它只依赖于继承。

      例如:

      public interface IBuilder {
          void Build();
      }
      
      public interface IBuilder<T> : IBuilder {
          T BuildParameter {get;}
      }
      

      注意:BuildParameter 对应于您的BuildCollagePattern

      然后你可以这样实现接口:

      public class SpecificBuilder : IBuilder<Int32> {
          // The specific constructor
          public SpecificBuilder(int param) { BuildParameter = param; }
      
          // Implement from IBuilder
          public void Build() {
              System.Console.WriteLine("Building with Int32: " + BuildParameter);
          }
      
          // Implement from IBuilder<T>
          public Int32 BuildParameter {get; private set;}
      }
      

      然后您可以将任何IBuilder&lt;T&gt; 传递为IBuilder

      public class Program {
          public static void Main() {
              SpecificBuilder builder = new SpecificBuilder(42);
      
              // SpecificBuilder implements IBuilder<Int32>
              // Build accepts any IBuilder
              // So this is legal:
              Build(builder);
          }
      
          //
          // Note this method accepts anything that inherits from IBuilder
          // 
          public static void Build(IBuilder builder) {
      
              builder.Build();
      
              // If you'd need access to the BuildParameter of IBuilder<T>
              // then this pattern fails you here.
              // Unless of course you want to check for types and cast
          }
      }
      

      如前所述:一旦您需要访问实现IBuilder&lt;T&gt; 的类之外的泛型类型,您就需要开始区分类型并相应地转换它们。没那么优雅。

      但是您可以通过这种方式设计很多东西并保持可扩展性。我提出了这个问题,因为我自己使用这种模式来实现图像过滤器,而您的BuildCollagePattern 可能非常适合这种设计模式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-19
        • 1970-01-01
        • 2016-08-13
        • 1970-01-01
        相关资源
        最近更新 更多