我正在为“可运行”的东西开发一个迷你框架。 (它们是实验、测试、任务等)
// Something that "runs" (in some coordinated way) multiple "runnable" things.
interface IRunnableOf<T> where : IRunnable
// Provide base-class functionality for a "runner"
abstract class RunnerBase<T> : IRunnableOf<T>
class SequentialRunner<T> : RunnerBase<T> // Same interface, different behavior.
class ConcurrentRunner<T> : RunnerBase<T>
// other types of runners.
class ConcurrentBlockRunner : SequentialRunner<Block>
class SequentialBlockRunner : ConcurrentRunner<Block>
现在,我该如何协调 ConcurrentBlockRunner
和 SequentialBlockRunner
?我的意思是:
通过共同的祖先来引用它们,以便在集合中使用。 (
IEnuerable<T>
其中 T = ??)提供额外的基类功能。 (例如,添加属性)。
我通过添加另一个接口(interface)来补救 #1,该接口(interface)刚刚将类型参数指定给 IA<T>
:
interface IBlockRunner : IRunnableOf<Block> { }
并修改了我的ConcurrentBlockRunner
和 SequentialBlockRunner
定义为:
class ConcurrentBlockRunner : SequentialRunner<Block>, IBlockRunner
class SequentialBlockRunner : ConcurrentRunner<Block>, IBlockRunner
自 ConcurrentBlockRunner
和 SequentialBlockRunner
都使用 Block
对于他们的类型参数,这似乎是一个正确的解决方案。然而,我不禁对此感到“奇怪”,因为好吧,我只是把那个界面加了上去。
对于#2,我想向ConcurrentBlockRunner
添加几条公共(public)数据。和 SequentialBlockRunner
.有几个属性适用于它们,但不适用于它们唯一的公共(public)基类,它一直在 RunnerBase<T>
。 .
这是我第一次在使用 C# 时感觉到多重继承会有所帮助。如果我能做到:
abstract class BlockRunnerBase {
int Prop1 { get; set; }
int Prop2 { get; set; }
class ConcurrentBlockRunner : SequentialRunner<Block>, BlockRunnerBase
class SequentialBlockRunner : ConcurrentRunner<Block>, BlockRunnerBase
然后我可以简单地将这些额外的属性添加到 BlockRunnerBase,一切都会正常工作。有没有更好的办法?
我知道我会立即被推荐考虑composition ,我开始使用它:
class BlockRunner : IBlockRunner {
IBlockRunner _member;
int Prop1 { get; set; } // Wish I could put these in some base class
int Prop2 { get; set; }
// Lots of proxy calls, and proxy events into _member
void Method() { _member.Method(); }
event SomeEvent
{
add { _member.SomeEvent += value; }
remove { _member.SomeEvent -= value; }
}
}
我遇到的问题(促使我写这个问题)是一旦你组合,你就失去了类型兼容性。在我的例子中,_member 触发了一个事件,所以 sender
参数类型为 SequentialBlockRunner
.但是,事件处理程序试图将其转换为类型 BlockRunner
,这当然失败了。那里的解决方案不使用 add
/remove
代理事件,但实际上处理它们,并引发我自己的事件。这么多的工作只是为了添加几个属性......
最佳答案
Composition over Inheritance , 好吧!
更明确地说:
class SequentialRunner<T> : RunnerBase<T>
应该实现IRunnableOf<T>
并代理 RunnerBase<T>
没有继承它。
class SequentialRunner<T> : IRunnableOf<T>
{
private readonly RunnerBase<T> _runnerBase;
...
}
关于c# - 如何处理 C# 中缺少多重继承的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10988695/