C# 通过包装类重写类方法
我试图想出一个非常简洁的方法来改变现有的类。我将尝试用这个例子来解释我的想法C# 通过包装类重写类方法,c#,inheritance,architecture,polymorphism,C#,Inheritance,Architecture,Polymorphism,我试图想出一个非常简洁的方法来改变现有的类。我将尝试用这个例子来解释我的想法 abstract class AbstractX { public abstract string X(); protected internal abstract int Y(); } // Execute all methods on another instance of AbstractX // This is why the method(s) are 'protected *interna
abstract class AbstractX
{
public abstract string X();
protected internal abstract int Y();
}
// Execute all methods on another instance of AbstractX
// This is why the method(s) are 'protected *internal*'
class WrappedX : AbstractX
{
AbstractX _orig;
public WrappedX(AbstractX orig)
{
_orig = orig;
}
public override string X()
{
return _orig.X();
}
protected internal override int Y()
{
return _orig.Y();
}
}
// The AbstractX implementation I start with
class DefaultX : AbstractX
{
public override string X()
{
// do stuff
// call Y, note that this would never call Y in WrappedX
var y = Y();
return y.ToString();
}
protected internal override int Y()
{
return 1;
}
}
// The AbstractX implementation that should be able to alter *any* other AbstractX class
class AlteredX : WrappedX
{
public AlteredX(AbstractX orig)
:base(orig)
{
}
protected internal override int Y()
{
Console.WriteLine("Sweet, this can be added to any AbstractX instance!");
return base.Y();
}
}
对,所以我打算用的方式是,
AbstractX x = new DefaultX();
x = new AlteredX(x);
Console.WriteLine(x.X()); // Should output 2 lines
或者暂时远离抽象的例子,让它更具体(应该是不言自明的)
但是(回到抽象的例子)这是行不通的。调用AlteredX.X()
的那一刻(它没有被覆盖),它会转到WrappedX.X()
,当然它运行DefaultX.X()
,它使用自己的Y()
方法,而不是我在AlteredX中定义的方法。
它甚至不知道它的存在
我希望这是显而易见的为什么我希望这是工作,但我会进一步解释,以确保
如果我不使用WrappedX
创建AlteredX,
AlteredX将不会“适用”于任何AbstractX实例,
这样就不可能像上面的FileWriter
那样。而不是
FileWriterAbstract
FileWriterDefault : FileWriterAbstract
FileWriterWrap : FileWriterAbstract
FileWriterSplit : FileWriterWrap
FileWriterLogged : FileWriterWrap
它将成为,
FileWriterAbstract
FileWriterDefault : FileWriterAbstract
FileWriterSplit : FileWriterDefault
// Implement Logged twice because we may want to use it with or without Split
FileWriterLogged : FileWriterDefault
FileWriterLoggedSplit : FileWriterSplit
如果我创建了一个新的,我必须实现它4次,因为我想让它可以用
Default
Split
Logged
Split+Logged
等等
考虑到这一点,实现这一目标的最佳方式是什么?我能想到的最好的(未经测试)是
classdefaultx:AbstractX
{
受保护的内部重写Func xf{get;set;}
受保护的内部重写函数yf{get;set;}
公共默认值x()
{
xf=XDefault;
yf=故障;
}
公共重写字符串X()
{
返回xf();
}
受保护的覆盖int Y()
{
返回yf();
}
字符串XDefault()
{
var y=y();
返回y.ToString();
}
int故障()
{
返回1;
}
}
类AlteredX:WrappedX
{
Func_yfOrig{get;set;}
公共AlteredX()
{
//我假设在设置时不会覆盖该类成员
//下面一行中的base.yf。
_yfOrig=base.yf;
base.yf=yalter;
}
私家侦探()
{
WriteLine(“很好,这可以添加到任何AbstractX实例中!”);
返回yfOrig();
}
}
即使这真的有效,它看起来真的很混乱。。。有人有什么建议吗?我想你把作文和继承弄混了 在AlteredX对象上调用x.x()时,该对象将调用其基本对象(WrappedX)的x方法。基本对象本身调用已包装的DefaultX类型的对象。现在对DefaultX(_orig)的对象调用Y方法。您希望(u orig)知道调用方的调用方中存在被覆盖的内容!但是怎么做呢
在这个调用链中,我看不到涉及重写方法Y的任何点。处理这个问题的一种方法是将所有内部操作推迟到一个单独的、可能的内部实用程序类,并为包装类提供一种替换实用程序类实现的方法。注意:此示例需要任何具体的非包装类来实现实用程序类。包装类可以选择也可以不选择包装实用程序类。这里的关键是基(抽象)类中实用程序类的getter/setter不允许重写它,因此每个继承类都使用由其构造函数定义的实用程序类。如果它选择不创建自己的实用程序,它将默认为它所包装的类的实用程序,最终使其返回到具体的、未包装的组合根类(如果需要) 注意:这非常复杂,我会避免这样做。如果可能,请使用标准装饰器,并且仅依赖包装类的公共接口方法。此外,实用程序类不必是内部类。它们可以通过构造函数注入,这可能会使它更干净一些。然后,您还可以在实用程序上显式地使用Decorator模式
public interface IFoo
{
string X();
}
public abstract class AbstractFoo : IFoo
{
public abstract string X();
protected internal Footilities Utilities { get; set; }
protected internal abstract class Footilities
{
public abstract int Y();
}
}
public class DefaultFoo : AbstractFoo
{
public DefaultFoo()
{
Utilities = new DefaultFootilities();
}
public override string X()
{
var y = Utilities.Y();
return y.ToString();
}
protected internal class DefaultFootilities : Footilities
{
public override int Y()
{
return 1;
}
}
}
public abstract class AbstractWrappedFoo : AbstractFoo
{
protected readonly AbstractFoo Foo;
public AbstractWrappedFoo(AbstractFoo foo)
{
Foo = foo;
}
public override string X()
{
return Foo.X();
}
}
public class LoggedFoo : AbstractWrappedFoo
{
public LoggedFoo(AbstractFoo foo)
: base(foo)
{
Foo.Utilities = new LoggedUtilities(Foo.Utilities);
}
public override string X()
{
return Foo.X();
}
protected internal class LoggedUtilities : Footilities
{
private readonly Footilities _utilities;
public LoggedUtilities(Footilities utilities)
{
_utilities = utilities;
}
public override int Y()
{
Console.WriteLine("Sweet");
return _utilities.Y();
}
}
}
现在这个节目
class Program
{
static void Main(string[] args)
{
AbstractFoo foo = new LoggedFoo(new DefaultFoo());
Console.WriteLine(foo.X());
}
}
产生
Sweet!
1
你所想到的看起来像是装饰图案,@Alireza我知道,这并没有改变我正在寻找问题解决方案的事实。@tvanfosson是的,看起来像。那个wiki页面只显示了一些示例,这些示例并不试图覆盖公共方法调用的特定方法,所以我的问题是,你把问题通读了吗?我已经知道这是一个问题,但我仍然在寻找一个解决方案来做我正在尝试做的事情。谢谢你的回答。在许多方面,这与我在问题末尾的内容相同,只是您使用的是类而不是Action/Func。我想这意味着没有更好的选择了,所以我会坚持下去。@natli看起来都太复杂了,但考虑到一个抽象的问题,很难给你更好的建议。我想我应该尝试删除内部/受保护方法的重用。在实际问题中,如果看不到你在做什么,很难说怎么做。
class Program
{
static void Main(string[] args)
{
AbstractFoo foo = new LoggedFoo(new DefaultFoo());
Console.WriteLine(foo.X());
}
}
Sweet!
1