希望有一个通用的包装器类可用

3

为了继承的目的,我希望有以下类可用,但我自己无法编写:

class Wrapper<G> : G
{
    public Wrapper(G base);
    protected G GetBase();
}

它将像往常一样继承G的所有成员,并且这些成员的所有用法都将重定向到在构造期间提供的G。

在像C#这样的语言中增加这个功能是否在技术上可行?

我想使用这个功能的主要用例是:

    class Wrapper<G> : G
    {
        public Wrapper(G g);
    }

    class IGraphNode<G> where G : IGraphNode<G>
    {
        IEnumerable<G> ForwardNodes();
        IEnumerable<G> BackwardNodes();
    }

    //Reverses the direction of the graph.
    class Reverse<G> : Wrapper<G> where G : IGraphNode<G>
    {
        public Reverse(G g)
            : base(g)
        { }

        IEnumerable<G> ForwardNodes()
        {
            return base.BackwardNodes();
        }

        IEnumerable<G> BackwardNodes()
        {
            return base.ForwardNodes();
        }
    }

2
你有更具体的例子来说明G是什么,Wrapper需要做什么吗? - epitka
2
常规继承有什么问题吗?已经实现的那种? - Cody Gray
2
'extends'?你是指Java吗? - Bala R
我认为他想要扩展类型为G的对象的功能。但这不正是在.Net中使用扩展的目的吗?请看下面的例子。 - Tomas Jansson
你是否正在尝试使用装饰器模式?请参考:http://www.dofactory.com/Patterns/PatternDecorator.aspx#_self1 - dashton
4个回答

1

不确定这是否符合您的要求,但您可以使用DynamicProxy在运行时创建包装对象,并根据需要拦截方法和属性调用。


0

这不是扩展的用途吗?

public static class MyStringExtensions
{
    public static string Add1ToString(this string myString)
    {
        myString += "1";
        return myString;
    }
}

在另一个类中,您现在可以使用以下内容:
using YourNamespaceOfTheExtensionMethods;

public class OtherClass
{
    public string DoSomething()
    {
        string someString = "Hello";
        return someString.Add1ToString();
    }
}

我以string为例,但如果您愿意,也可以扩展Object


我相信他希望在GenericExtensions<T>上调用MyClassA的所有方法时,都能调用MyClassA实例的方法。如果这样说有意义的话... :) - Szymon Rozga
我注意到就在我发布答案后 :) - Tomas Jansson
删除了第一个答案,因为我认为他可能只是在使用扩展程序。 - Tomas Jansson

0
你可能可以使用反射来实现这个。但是你的目标到底是什么?是为了装饰一个类,还是创建能够处理它的工具?以你想要的方式扩展一个已有类的实例似乎很冒险,因为你不会创建基类的新实例,而使用该对象的代码将不知道这一点。也就是说,属性可能会更改新对象,也可能会更改某些其他扩展对象,语法无法确定确切的功能。
我认为更透明(通常)的做法是只需执行例如:
class Wrapper<G> where G: SomeType
{
    public G Base;
    public Wrapper(G g) {
        Base = g;
    }

    // methods to do stuff with object supplied at construction
}

你可以不使用where来实现这个,但我想不出为什么你不关心基础类型的原因。

如果你真的想要创建一个新类,具有新属性,并继承现有类的数据,我认为你可能过于努力了,因为这并没有什么意义:两个对象将不再以合理的方式绑定。也就是说,基类属性的更改将影响与您的扩展属性不同的对象。在这个例子中,如果你在MyWrapper.Base中有属性,那么保持对基类的对象引用似乎更具概念上的合理性,如果这确实是你的目标。否则,使用你的扩展对象的客户端将无法理解这一点,你很容易就会不知道为什么你的代码不能正常工作...

如果你想创建一个扩展某些东西的新对象,并以某种透明的方式复制现有对象的属性,则可以像这样做:

class Wrapper<G>: G
{
    public Wrapper(G g) {
        // add memberwise copy function
    }
    .. more properties
}

Wrapper<SomeType> newWrapper = Wrapper<SomeType>(someOtherObject);

就像您可以从现有的列表创建一个新列表一样。


我认为他想要的是扩展方法。我的猜测是他想要给一个已经存在的类“添加”一些功能,而这正是扩展方法的用途。 - Tomas Jansson
我觉得你可能是对的。虽然我仍然觉得有一些别有用心的动机存在,因为如果使用自己的对象,为什么不将这些方法包含在核心设计中,或者使用基类和继承来创建对象的不同版本呢?但是,如果他的目标只是装饰其他人的东西,那就是这样做的方式。不过我的直觉告诉我,他想添加属性,而不仅仅是方法。 - Jamie Treworgy

0

我记得 Ruby 中有这个功能,但忘了它叫什么。C# 不支持此功能。是否可以在 C# 中添加此功能?如果您能说服 .Net 和 C# 团队实现此功能,那当然可以...但我怀疑他们会这样做。


1
在C++中,它被称为CRTP(好奇的递归模板模式)。在Ruby中,它可能也被称为“mixin”,尽管从技术上讲,那是另一回事,但在C++中有时会使用CRTP来实现 mixins。 - Konrad Rudolph
@Konrad:有趣。我认为这是Ruby中的委托模式。 - Szymon Rozga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接