重用实现的更好方法是什么:继承还是泛型?
模型如下:脚本有步骤,步骤有元素。树结构是双重链接的,即步骤知道他们的脚本和元素现在是他们的步骤。
现在,有两种类型的脚本:模板和运行,其中首先创建一个Run作为模板的副本。这导致2个类似的层次结构ScriptTemplate-> ScriptTemplateStep-> ScriptTemplateElement和ScriptRun-> ScriptRunStep-> ScriptRunElement。大多数功能都很常见,但是各种类可能都有一些额外的属性。
为了重用功能,我可以开发抽象的Script类,它将由ScriptRun和ScriptTemplate派生,如:
abstract class Script { IList<Step> Steps; }
class ScriptRun : Script {}
class ScriptTemplate : Script {}
class Step { Script Script; IList<Element> Elements; }
class ScriptRunStep : Step {}
class ScriptTemplateStep : Step {}
或者我可以尝试泛型:
abstract class Script<TScript, TStep, TElement>
where TScript:Script<TScript, TStep, TElement>
where TStep:Step<TScript, TStep, TElement>
where TElement:Element<TScript, TStep, TElement>
{ IList<TStep> Steps; }
abstract class Step<TScript, TStep, TElement>
where TScript:Script<TScript, TStep, TElement>
where TStep:Step<TScript, TStep, TElement>
where TElement:Element<TScript, TStep, TElement>
{ TScript Script; IList<TElement> Elements; }
class ScriptRun : Script<ScriptRun, ScriptRunStep, ScriptRunElement> {}
class ScriptRunStep : Step<ScriptRun, ScriptRunStep, ScriptRunElement> {}
class ScriptRunElement : Element<ScriptRun, ScriptRunStep, ScriptRunElement> {}
class ScriptTemplate : Script<ScriptTemplate, ScriptTemplateStep, ScriptTemplateElement> {}
class ScriptTemplateStep : Step<ScriptTemplate, ScriptTemplateStep, ScriptTemplateElement> {}
class ScriptTemplateElement : Element<ScriptTemplate, ScriptTemplateStep, ScriptTemplateElement> {}
仿制药方法的缺点:
专业人士:
abstract class Script { abstract Step NewStep(); }
abstract class ScriptRun {
override Step NewStep(){
var step = new ScriptRunStep();
this.Steps.Add(step);
return step;
}
}
abstract class ScriptTemplate {
override Step NewStep(){
var step = new ScriptTemplateStep();
this.Steps.Add(step);
return step;
}
}
在泛型场景中,您写道:
abstract class Script<TScript, TStep, TElement>
where TScript:Script<TScript, TStep, TElement>
where TStep:Step<TScript, TStep, TElement>, new()
where TElement:Element<TScript, TStep, TElement>
{
TStep NewStep() {
var step = new TStep();
this.Steps.Add(step);
return step;
}
}
并且ScriptRun和ScriptTemplate自动拥有该方法,或者更好的方法:返回类型分别为ScriptRunStep和ScriptTemplateStep,而不仅仅是Step。
答案 0 :(得分:2)
我发现泛型通过通用属性来促进组合,而不必为要利用的每个组合编写不同的类,或者必须创建冗长的继承树。我尽力支持组合继承,特别是在单继承平台上。
我说你的情况需要两者兼顾。也许类似于以下内容:
class Child<TParent> { TParent Parent; } class Parent<TChild> { IList<TChild> Children; } class ParentAndChild<TParent, TChild> : Parent<TChild> { TParent Parent; } class Element : Child<Step> { ... } class Step : ParentAndChild<Script, Element> { ... } class Script : Parent<Step> { ... }
这样的东西可以促进双链接对象层次结构中的大部分功能。
答案 1 :(得分:1)
都不是。重用实现的最佳方法是聚合。
之后,如果模板是可应用的,则取决于问题。我的经验法则是,产生最少量代码的任何东西都会更好。至少,那是我的经历。
[编辑] 对于这样一个精心设计的问题,这可能是一个简短的答案。
但是,特别针对这种情况(看起来主要是关于重用父子层次结构的逻辑,你可以写
IChildOf<TPARENT>
{ TPARENT Parent {get; set;} }
sealed class Children<TPARENT,TCHILD> : where TCHILD: IChildOf<TPARENT>
{
// .... details omitted
public void Add(TCHILD child)
{
// add child to internal collection, then:
child.Parent = parent;
}
readonly TPARENT parent;
}
TPARENT
将有一个孩子&lt;&gt;集合作为成员,并将指针传递给自己。该集合确保每个TCHILD
都有对其父级的引用。
答案 2 :(得分:0)
查看您的优缺点列表 - 我怀疑您已经知道了答案。缺点通常是“我不熟悉这个”,“它不那么有效”,而专业人员的形式是“它在我的代码上强制执行更严格的结构”。我说,总是选择使代码更健壮的那个,这是泛型。