【问题标题】:How to improve design of the program considering interfaces and abstract classes?如何改进考虑接口和抽象类的程序设计?
【发布时间】:2019-08-23 12:23:04
【问题描述】:

考虑到已接受的答案here,一般建议的想法是,在可能的情况下,倾向于定义类而不是接口。

考虑以下设计:

  1. 基类ChessPiece,其中还定义了多个子类
  2. 某些类型的片段如果已经被移动,则需要记录(即PawnRookKing):bool HasMoved 属性
  3. 一类棋子,即King无法捕获;其他一切都可以是:bool IsCaptured 属性

问题是因为派生类King在#2和3中常见的#2和3之间的冲突(如果我只实现两者中的一个就没有问题)。

理想情况下,应该实现两个抽象类CapturablePieceMoveRecordedPiece,它们都继承自ChessPiece。但是 C#不允许多类继承,这就是接口的用武之地。

如果实现了接口,现在所有具体的子类都可以手动实现每个必需的属性。那么考虑这个例子:

// needed type-check
ChessPiece piece;
// some calculations...
if (piece is ICapturablePiece)    // or using the 'as' keyword
//or...
if (piece is IMoveRecordedPiece)
// which in the case of non-conflicting abstract classes,
// this is easily doable and valid because of
// inheritance to the base class

我不能这样做,因为接口是原样的。它不能从任何东西继承,它只是必须实现的方法的独立标记。

抽象类版本仍然更可取 - CapturablePieceMoveRecordedPiece,因为它的基本类型是 ChessPiece,我确信这个逻辑是“is-an " 而不是 "can-do"(如上面的链接中所述)。

我现在的问题是,我将如何改进设计考虑:

  1. 你不能继承多个类,接口不能继承任何东西。
  2. 抽象类优于接口
  3. 需要类型检查的代码块

编辑:

这不是链接问题的重复。这更像是在考虑接口和抽象类的同时如何改进设计

【问题讨论】:

  • 我猜大部分人都回答了here
  • 请记住,Microsoft 设计指南中的“首选类而不是接口”来自于向后兼容的问题——你不能在不破坏向后兼容的情况下向接口添加方法。如果这些类型都只是在你自己的代码中使用,那不是问题,所以不用担心。在你的例子中,我会使用接口——接口描述对象的一些行为——“这个对象可以被捕获”,“这个对象可以保留它的移动历史”等等。虽然在实践中,我不会使用这里的任何接口:ChessPiece 将有 bool IsCaptured
  • 再次阅读您的问题,您能解释一下“我不能这样做,因为接口是原样的” 是什么意思吗?
  • This series 作者是 Eric Lippert,对于试图将类型系统与游戏规则结合起来的人们来说,这是必读的。确保您阅读了所有 5 个部分 - 第 5 部分尤其重要。
  • 再次感谢@John。

标签: c# oop abstract-class abstraction


【解决方案1】:

相互独立地定义行为,并通过需要的实例对其进行聚合。 你的问题不是继承,而是一个类的责任太多。国王与兵的移动方式不同。所以独立定义这些类型的行为并将其添加到国际象棋图形类中。类似于运动。在外部实现该行为并将其传递给需要它的类。

这可以让你很好地解耦你的代码。

【讨论】:

  • 我的问题是不是每件棋子的走法不同,而且它们的排序很好(Pawn 的走法实现与 King 的不同,等等)。这是关于实现上述问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-19
  • 1970-01-01
  • 2014-04-12
  • 1970-01-01
  • 1970-01-01
  • 2020-10-20
  • 1970-01-01
相关资源
最近更新 更多