我试图想出一种非常巧妙的方法来改变现有的课程。我将尝试用这个例子来解释我想出什么;
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
或者暂时离开抽象的例子,让它更具体(应该是不言自明的);
FileWriterAbstract writer = new FileWriterDefault("path/to/file.ext");
writer = new FileWriterSplit(writer, "100MB");
writer = new FileWriterLogged(writer, "path/to/log.log");
writer.Write("Hello");
但是(回到抽象的例子)这是行不通的。那一刻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
等等...
因此,考虑到这一点,实现这一目标的最佳方法是什么?我能想到的最好的(未经测试的)是;
class DefaultX : AbstractX
{
protected internal override Func<string> xf { get; set; }
protected internal override Func<int> yf { get; set; }
public DefaultX()
{
xf = XDefault;
yf = YDefault;
}
public override string X()
{
return xf();
}
protected override int Y()
{
return yf();
}
string XDefault()
{
var y = Y();
return y.ToString();
}
int YDefault()
{
return 1;
}
}
class AlteredX : WrappedX
{
Func<int> _yfOrig { get; set; }
public AlteredX()
{
// I'm assuming this class member doesn't get overwritten when I set
// base.yf in the line below.
_yfOrig = base.yf;
base.yf = YAltered;
}
private int YAltered()
{
Console.WriteLine("Sweet, this can be added to any AbstractX instance!");
return yfOrig();
}
}
即使这确实有效,它似乎真的很混乱......有没有人有任何建议?