我需要对子类执行操作并返回结果:
public interface IEntity { }
public abstract class Entity : IEntity {
public abstract IEntity doStuff(IEntity e1, IEntity e2, IEntity e3);
}
public class Customer : Entity {
public override IEntity doStuff(IEntity e1, IEntity e2, IEntity e3) { // <-- yuck
var customer1 = e1 as Customer; // <-- yuck
var customer2 = e2 as Customer; // <-- yuck
var customer3 = e3 as Customer; // <-- yuck
// do stuff
return foo;
}
}
我想避免使用该子类的方法签名以及相关的类型转换。
所以我更喜欢这个:
public override Customer doStuff(Customer c1, Customer c2, Customer c3) {
// do stuff
return foo;
}
我如何使用类型系统来实现这一目标?
编辑:我将方法的名称从compare
更改为doStuff
,以重申操作本身无关紧要。我不想比较。我只是想改变类型。我该怎么做?
<小时/> 许多人都说要改变设计,但我做不到。我已经有了一个解决方案,我已经将其包含在下面了,它的确有效。如果您有更好的方法来实现这一点,而不是批评设计(这不是重点),请告诉我。感谢大家的贡献。
答案 0 :(得分:2)
这很有效。但是自我引用的泛型让我头疼。
public interface IEntity { }
public abstract class Entity<TEntity> : IEntity where TEntity : IEntity {
public abstract TEntity doStuff(TEntity e1, TEntity e2, TEntity e3);
}
public class Customer : Entity<Customer> {
public override Customer doStuff(Customer c1, Customer c2, Customer c3) {
// do stuff
return foo;
}
}
这是一个很好的解决方案,还是那里有陷阱会给我带来问题?
有更好的解决方案吗?
答案 1 :(得分:1)
在持续无知,序列化(JSON / XML)和网络传输二值化的前景中,没有接口你可能会更好。
为了区别也称为实体的POCO类,我更喜欢原始术语&#34;域对象&#34;正如埃里克埃文斯所说的那样。原创作品。
这只是我要做的一个例子。
public abstract class AbstractDomainObject<T>
where T : AbstractDomainObject
{
public abstract bool CanDoStuffWith(T other);
}
public class Customer : AbstractDomainObject<Customer>
{
public override bool CanDoStuffWith(Customer other)
{
return this.Gender != other.Gender;
}
}
答案 2 :(得分:1)
这个令人困惑的原因是这个
public abstract class Entity : IEntity {
public abstract IEntity doStuff(IEntity e1, IEntity e2, IEntity e3);
}
不应该实施IEntity
。如果您需要一个使用IEntity
“填充”的类,则该类与IEntity
分开。这是单一责任原则。除非IEntity
的主要目的是doStuff
,否则doStuff
不会属于同一类。
无论doStuff
做什么,这就是这个课程应该是什么。例如,如果它比较IEntity
的实例是否与某些操作兼容,则可以执行以下操作:
public interface ICompatibilityChecker<TEntity> where TEntity : IEntity
{
bool AreCompatible(TEntity entity, TEntity other);
}
然后你可能会发现你甚至不需要抽象类:
public class CompatibilityChecker : ICompatibilityChecker<Customer>
{
public bool AreCompatible(Customer entity, Customer other)
{
//check compatibility
}
}
涉及的另一个原则是Favor Composition Over Inheritance。当将功能放入完全独立的类中时,通常更有意义,因此倾向于将功能放入基类中。但请注意,当您将其中一些行为分离到不同的类中时,这些类的设计变得更加简单。
此外,如果您有不需要该行为的域对象,该怎么办?然后继承变得更加困难,因为您可能需要抽象类中的其他方法,但是您仍然无法实现另一个您甚至不需要的方法。
当我们尝试通过让它们从公共基类继承而在类之间共享功能时,它往往会被复杂化并最终崩溃。如果我们将行为和责任分成不同的类,那么维护起来要容易得多。