繁体   English   中英

将接口扩展为抽象类

[英]Extend interface to an abstract class

我有一个接口(移动)应该移动一些形状。

interface Move { move(); }
abstract class Shape : Move

class Circle : Shape
class Square : Shape
class Triangle : Shape

我的疑问是,我必须有一个移动Shapes的界面,但是只能移动Circle和Triangle,那么我如何从Square“移除”界面? 我应该从Shape中删除界面并在Circle和Triangle上手动添加它吗? 我有点困惑。 希望有人可以帮助我。

你应该像这样设置你的类:

interface IMovable { move(); } 
abstract class Shape : { } 

class Circle : Shape, IMovable { } 
class Square : Shape { } 
class Triangle : Shape, IMovable { } 

如果不是每个形状都可以移动,那么Shape不能实现接口。 另请注意,我将您的界面重命名为IMovable ,这不是一个大问题,但它更受欢迎,更好的命名约定。

您无法从继承树中删除接口。

你的模型似乎需要两个抽象类 - ShapeMovableShape

interface IMove { move(); } 
abstract class Shape : {} 
abstract class MovableShape : IMove, Shape {} 

class Circle : MovableShape{}
class Square : Shape{}
class Triangle : MovableShape{}

您应该让自己更熟悉接口,类和OO背后的想法。 您要说的是以下内容:

  • 每个形状都可以移动。
  • 方形是一种形状。
  • 但广场不能移动。

显而易见,这是没有道理的。 所以你必须调整你的课堂设计。 可以移动每个形状,Shape(和Square)应该实现Move,或者不能移动每个形状,然后Shape不应该实现Move。

试试这个:

interface IMove { move(); }
abstract class Shape { }

class Circle : Shape, IMove { }
class Square : Shape { }
class Triangle : Shape, IMove { }

其他选项可能只是在Shape类中实现IMove.Move方法并默认抛出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
     }
}

最佳答案取决于这些类的用例和环境。 作为开发应用程序或框架的团队的一部分,采用该团队使用的设计模式比寻求“完美”解决方案更可取,因为这将使其他人更容易采用和维护您的代码。

您希望如何使用和扩展这些类也很重要。 您是否期望'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之前。 默认行为应基于您希望使用代码的其他人的期望,具体取决于他们如何实现相关的设计模式。

通过查看集合类在不同框架中的可变性如何发展的历史,可以找到做出这些决策的挑战的一个很好的例子。 有些设计中可变类(集合,数组,字典等)已经成为基类,在子类中实现了不变性,反之亦然。 这两种方法都有有效的论据,也有动态方法,但对于框架用户来说最重要的因素是一致性,因为正确的是最容易使用的是什么,提供安全性和性能不是损害。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM