繁体   English   中英

如何编写指定创建逻辑的接口或抽象类?

How do I write an interface or abstract class that specifies creation logic?

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我有一个通用类,涉及可以从字符串反序列化的小部件。 通用类的实例将这些小部件之一的类型作为模板参数,然后从字符串创建这些小部件。 我希望使用C#泛型的协方差属性编写类似WidgetUser<IWidget>代码来处理可能是WidgetUser<RedWidget>WidgetUser<BlueWidget> 问题是要从WidgetUser<T>内的字符串创建窗口小部件,我被迫添加new()作为保护。 这使WidgetUser<IWidget>成为无效类型。 目前,我有这样的代码:

interface IWidget
{
    // Makes this widget into a copy of the serializedWidget
    void Deserialize(string serializedWidget);
}
class WidgetUser<T> where T : IWidget, new()
{
    public void MakeAndUse(string serializedWidget)
    {
        var widget = new T();
        widget.Deserialize(serializedWidget);
        Use(widget);
    }
}

使用此代码,我可以使WidgetUser<BlueWidget>很好,因为BigWidget满足new() 我不能编写WidgetUser<IWidget>因为不能保证IWidget实例(或等效的抽象类)可以与new() 解决方法可能是这样的:

abstract class WidgetUser
{
    public abstract void MakeAndUse();
}

class WidgetUser<T> : WidgetUser
    where T : IWidget, new() 
{ 
    /* same as before but with an 'override' on MakeAndUse */ 
}

使用此代码,我可以创建一个WidgetUser<BlueWidget>然后编写仅处理WidgetUser代码。 我可以用类似的代码使用抽象类BaseWidget代替IWidget来完成几乎相同的事情。 这是功能性的,但是我怀疑还有一种更直接的方法不会强迫我定义一个虚拟类。 如何在不创建伪类或额外工厂的情况下将意图传达给类型系统。 我只想要一个说“您可以从字符串中制作一个”的界面。

TL; DR:是否可以通过某种方法编写接口或抽象类,使我可以从字符串创建实例,但不需要我以new()作为WidgetUser<T>的保护WidgetUser<T>

2 个回复

我将实现WidgetFactory并调用WidgetFactory.Create<T>(serializedWidget)以避免使用new T()

这里的问题是您的Deserialize()方法应该是静态方法。 因此,它不应该是IWidget本身的成员-它应该是Factory接口的成员,或者应该是具体Widget类的静态成员,而该Widget类是从具体factory方法调用的。 我在下面显示后一种方法。

(或者,您可以使用Func<IWidget>委托来指定它,但更常见的是提供完整的工厂接口。)

因此,我建议您创建工厂界面:

interface IWidgetFactory
{
    IWidget Create(string serialisedWidget);
}

然后从IWidget删除Deserialize()

interface IWidget
{
    // .. Whatever
}

然后将静态Deserialize()方法添加到IWidget每个具体实现中:

class MyWidget: IWidget
{
    public static MyWidget Deserialize(string serializedWidget)
    {
        // .. Whatever you need to deserialise into myDeserializedObject
        return myDeserializedObject;
    }

    // ... Any needed IWidget-implementing methods and properties.
}

然后使用具体小部件类中的静态Deserialize()方法为具体小部件类实现工厂:

sealed class MyWidgetFactory : IWidgetFactory
{
    public IWidget Create(string serialisedWidget)
    {
        return MyWidget.Deserialize(serialisedWidget);
    }
}

然后向您的WidgetUser类添加一个构造函数,该构造函数接受IWidgetFactory并在MakeAndUse()使用它:

class WidgetUser
{
    public WidgetUser(IWidgetFactory widgetFactory)
    {
        this.widgetFactory = widgetFactory;
    }

    public void MakeAndUse(string serializedWidget)
    {
        var widget = widgetFactory.Create(serializedWidget);
        Use(widget);
    }

    private readonly IWidgetFactory widgetFactory;
}

请注意,在这种情况下,您不再需要WidgetUser的type参数,因此已将其删除。

然后,当您创建WidgetUser您必须提供一个工厂:

var widgetUser = new WidgetUser(new MyWidgetFactory());

...

widgetUser.MakeAndUse("MySerializedWidget1");
widgetUser.MakeAndUse("MySerializedWidget2");

通过工厂可带来更大的灵活性。

例如,假设您的序列化方案包括一种从序列化的字符串中分辨出它是哪种小部件的方法。 为了简单起见,假设它是"[MyWidget]"则以"[MyWidget]"开头;如果是MyWidget ,则以["MyOtherWidget"] MyOtherWidget

然后,您可以实现一个充当“虚拟构造函数”的工厂,该工厂可以在给定序列化字符串的情况下创建任何类型的小部件,如下所示:

sealed class GeneralWidgetFactory: IWidgetFactory
{
    public IWidget Create(string serialisedWidget)
    {
        if (serialisedWidget.StartsWith("[MyWidget]"))
            return myWidgetFactory.Create(serialisedWidget);
        else if (serialisedWidget.StartsWith("[MyOtherWidget]"))
            return myOtherWidgetFactory.Create(serialisedWidget);
        else
            throw new InvalidOperationException("Don't know how to deserialize a widget from: " + serialisedWidget);

    }

    readonly MyWidgetFactory      myWidgetFactory      = new MyWidgetFactory();
    readonly MyOtherWidgetFactory myOtherWidgetFactory = new MyOtherWidgetFactory();
}

请注意,这通常不是执行操作的最佳方法-最好使用诸如Autofac之类的依赖容器来管理此类操作。

1 如何将抽象类转换为接口?

我有一个使用arraylists的java程序 - 这些arraylists存储'变量',其中'变量'是一个抽象类。 现在,为了节省内存,我想使用一个名为HugeCollections-VanillaJava的java库 - 但是这个库需要定义一个接口。 如何将抽象类转换为接口? ...

2 如何编写一个抽象类作为接口

我已经在Google上广泛搜索该问题的答案,但是我或者不知道该术语是什么,否则就不可能,因此请原谅我的任何无知。 首先是代码,然后是原因。 现在,通常我将抽象一个类来实现MyInterface ,但是在这种情况下,我不能这样做,因为Java(可以理解)不支持从多个类继承类(尽管接 ...

8 Java:如何编写同时指定超类和接口的强制转换?

我的Java程序中发生了类似的事情: 我怎样才能使它起作用? 如果不使用泛型,似乎无法在变量声明中同时指定基类和接口。 我不认为泛型在这里会起作用,因为o是使用反射动态创建的,因此在编译时不知道其实际类。 (是的,我知道这是一件很奇怪的事情。但是实际上,我确实需要超类和接口的功 ...

9 如何在 TS 中为具有原型方法的类编写接口?

我已经解决了这个问题一段时间了,并认为我最终会理解或遇到一个体面的解释。 我已经阅读了 TS 手册中的许多文章,google() 了它,并搜索了 SO,但还没有找到答案。 我需要知道如何在 TS 类/接口中正确且完整地键入原型方法。 我得到了这个可怕的“属性 'getChunkLength' ...

10 如何编写适配器类来模拟基本类型上的接口?

我有一个采用接口的方法。 我为每种原始类型(和字符串)写了一个自定义函数。 看起来是这样的: 尽管很繁琐,但为每个基本类型都具有Execute()是可行的。 问题是当我必须添加以下内容时: 每当我有一个要处理的新集合时,我都必须写出Execute()函数吗? 对于字典,我 ...

暂无
暂无

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

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