我有一个应该移动某些形状的界面(移动)。
interface Move { move(); }
abstract class Shape : Move
class Circle : Shape
class Square : Shape
class Triangle : Shape
我的疑问是,我必须有一个移动Shapes的界面,但是只能移动Circle和Triangle,那么如何从Square中“删除”界面?我应该从Shape中删除界面并在Circle和Triangle上手动添加它吗?我有点困惑。希望有人可以帮助我。
答案 0 :(得分:34)
你应该像这样设置你的课程:
interface IMovable { move(); }
abstract class Shape : { }
class Circle : Shape, IMovable { }
class Square : Shape { }
class Triangle : Shape, IMovable { }
如果不能移动每个形状,则Shape
不得实现界面。另请注意,我将您的界面重命名为IMovable
,这不是一个大问题,但它更受欢迎,也是更好的命名惯例。
答案 1 :(得分:27)
您无法从继承树中删除接口。
您建模的内容似乎需要两个抽象类 - Shape
和MovableShape
。
interface IMove { move(); }
abstract class Shape : {}
abstract class MovableShape : IMove, Shape {}
class Circle : MovableShape{}
class Square : Shape{}
class Triangle : MovableShape{}
答案 2 :(得分:3)
您应该让自己更熟悉接口,类和OO背后的想法。您要说的是以下内容:
显然这没有道理。所以你必须调整你的课堂设计。每个形状都可以移动,Shape(和Square)应该实现Move,或者不能移动每个形状,然后Shape不应该实现Move。
答案 3 :(得分:3)
试试这个:
interface IMove { move(); }
abstract class Shape { }
class Circle : Shape, IMove { }
class Square : Shape { }
class Triangle : Shape, IMove { }
答案 4 :(得分:2)
其他选项可能只是在IMove.Move
类中实现Shape
方法,默认情况下会抛出NotSupportedException
。
public abstract class Shape : IMove
{
public virtual void Move()
{
throw new NotSupportedException();
}
}
所以在一天结束时,“任何形状都可以移动”,但“可移动的形状应该提供自己的移动方式”。
最后,让我们想象一下,有一堆形状以同样的方式移动。您将创建一个DefaultMovableShape
抽象类派生Shape
,它将覆盖Shape.Move
虚拟方法。
public abstract class DefaultMovableShape
{
public override void Move()
{
// Do stuff
}
}
答案 5 :(得分:2)
最佳答案取决于这些类的用例和环境。作为开发应用程序或框架的团队的一部分,采用该团队使用的设计模式比寻求完美的设计模式更可取。解决方案,因为它将使其他人更容易采用和维护您的代码。
您希望如何使用和扩展这些类也很重要。你会期待' Square'需要在将来移动? Shape的可移动性是否始终是静态的,还是作为动态属性更有用? Move()对于不是形状的类有什么价值吗?如果可移动性可用作动态属性,请考虑以下事项:
public abstract class Shape
{
public bool isMovable()
{
return false;
}
public virtual void Move()
{
if (!isMovable() {
throw new NotSupportedException();
} else {
throw new BadSubclassException();
}
}
}
您的子类可以覆盖isMovable以提供静态或动态行为,并且可以进一步修改或子类化,只要您的文档明确指出isMoveable应始终在调用Move之前。默认行为应基于您希望使用代码的其他人的期望,具体取决于他们如何实施相关的设计模式。
通过查看集合类在不同框架中的可变性如何发展的历史,可以找到做出这些决策的挑战的一个很好的例子。有些设计中可变类(集合,数组,字典等)已经成为基类,在子类中实现了不变性,反之亦然。这两种方法都有有效的论据,也有动态方法,但对于框架用户来说,最重要的因素是 一致性, ,因为正确的是真正的关于什么是最容易使用的问题,提供安全性和性能不会受到影响。