简体   繁体   English

创建接口子类的实例

[英]Create instance of interface child class

I have interface and 3 classes that derives it, but how use 1 variable for each one type? 我有接口和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>{}

And I need create instance of class when it`s necessary 我需要在必要时创建类的实例

I have IBuilder<IConvertible> currentBuilder variable, but I cannot create instance of any Builder 我有IBuilder<IConvertible> currentBuilder变量,但我无法创建任何Builder实例

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

Only if I change IBuilder<IConvertible> currentBuilder to IBuilder<SimpleCollagePatterns> currentBuilder or atother type I can create this type of Builder, but I need to have abulity create any type 只有当我将IBuilder<IConvertible> currentBuilder更改为IBuilder<SimpleCollagePatterns> currentBuilder或其他类型时,我才能创建这种类型的Builder,但我需要abulity创建任何类型

I faced the same scenario. 我遇到了同样的情况。 But ended up to find there is no solution for this. 但最终发现没有解决方案。 It is not possible to create object of any type in run time. 在运行时无法创建任何类型的对象。 As you said, changing IBuilder currentBuilder to IBuilder currentBuilder is the only way to create object for SimpleBuilder type. 正如您所说,将IBuilder currentBuilder更改为IBuilder currentBuilder是为SimpleBuilder类型创建对象的唯一方法。 Similarly for other cases. 其他情况也是如此。

If you really want to use one variable for all scenarios, you can always define it as a simple object to hold on to the instance and use the IS operator to see which type it really is when necessary like this: 如果你真的想在所有场景中使用一个变量,你总是可以将它定义为一个简单的对象来保持实例并使用IS运算符来查看它在必要时的真实类型,如下所示:

if (this.currentBuilder is SimpleBuilder) { } if(this.currentBuilder是SimpleBuilder){}

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

public interface IBuilder<out T>

What you want to read about is called covariance , which is denoted by keyword out beside a generic type parameter in the interface declaration. 您想要阅读的内容称为协方差 ,它在接口声明中的泛型类型参数旁边用关键字out表示。

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

This will allow you to declare a variable of type IBuilder<IConvertible> and assign eg. 这将允许您声明IBuilder<IConvertible>类型的变量并分配例如。 SimpleBuilder to it, you just need to be aware of what consequences applying covariance has, the most important being, in plain words, generic type can only be used as return type of the type members. SimpleBuilder ,它只需要知道应用协方差的后果,最重要的是,用简单的话来说,泛型类型只能用作类型成员的返回类型。

If you can't change the IBuilder interface - there is no option to create a variable for all cases. 如果您无法更改IBuilder接口 - 则无法为所有情况创建变量。

For further info you can research SO, eg. 有关详细信息,您可以研究SO,例如。 Difference between Covariance & Contra-variance or read at the source, eg. 协方差和反方差之间的差异或从源头读取,例如。 https://msdn.microsoft.com/en-us/library/mt654055.aspx . https://msdn.microsoft.com/en-us/library/mt654055.aspx

If you don't need public access to the generic type 如果您不需要公共访问泛型类型

In particular if SimpleCollagePatterns is used exclusivly by the class that implements that particular interface (In this case ShapeBuilder ), then you don't need covariance . 特别是如果SimpleCollagePatterns由实现特定接口的类(在本例中为ShapeBuilderShapeBuilder ,那么您不需要协方差

There is a simple design pattern that relies on inheritance alone. 有一种简单的设计模式仅依赖于继承。

For example: 例如:

public interface IBuilder {
    void Build();
}

public interface IBuilder<T> : IBuilder {
    T BuildParameter {get;}
}

Note: The BuildParameter corresponds to your BuildCollagePattern 注意: BuildParameter对应于您的BuildCollagePattern

Then you can implement the interface as such: 然后你可以这样实现接口:

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;}
}

Then you can pass around any IBuilder<T> as an IBuilder 然后你可以传递任何IBuilder<T>作为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
    }
}

As noted before: Once you need access to the generic type outside of the class thats implementing the IBuilder<T> you'd need to start differentiating types and cast them accordingly. 如前所述:一旦您需要访问实现IBuilder<T>的类之外的泛型类型,您需要开始区分类型并相应地转换它们。 Not so elegant. 不那么优雅。

But you can design lot's of stuff this way and maintain extensibility. 但是你可以用这种方式设计很多东西并保持可扩展性。 I bring this up, as I have used this pattern to implement image filters myself and your BuildCollagePattern might be very much realizable with this design pattern. 我提出这个问题,因为我已经使用这种模式自己实现了图像过滤器,并且使用这种设计模式可以很好地实现BuildCollagePattern

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM