我想我理解界面和抽象之间的区别。抽象设置默认行为,在纯抽象的情况下,行为需要由派生类设置。接口是一个你需要的东西,而不需要基类的开销。那么界面相对于构图的优点是什么?我能想到的唯一优点是在基类中使用受保护的字段。我错过了什么?界面vs构图
界面vs构图
回答
一个接口定义了你将如何使用。
您继承以便重用。这意味着你想要适应一些框架。如果你不需要适应框架,即使你自己制作一个框架,也不要继承。
构图是实现细节。为了获得基类的实现,不要继承,编写它。只有在允许您适合框架的情况下才能继承。
接口定义了行为。抽象类有助于实现行为。
从理论上讲,纯粹的抽象类没有任何实现和接口之间没有太大的区别。两者都定义了未实现的API。然而,纯粹的抽象类经常被用在不支持提供接口(如语义)的接口的语言中(如C++)。
当你有选择时,通常抽象基础将提供某种程度的功能,即使它不完整。它有助于实现共同的行为。不利的一面是你被迫从中得出结论。在简单定义使用情况时,请使用界面。 (没有什么能阻止你创建一个实现接口的抽象基础)。
接口很薄,在C++中它们可以被描述为只有纯虚函数的类。薄是好事,因为
- 它减少了在使用或实现的接口
- 它减少了用户与接口的实现之间的耦合(依赖)的学习曲线。因此,用户可以很好地隔离他们正在使用的界面的实施变化。
这与动态库链接的同时,有助于促进即插即用,最近一个时期的无名英雄,但伟大的软件创新之一。这导致更大的软件互操作性,可扩展性等。
接口可以做更多的工作。当你有一个重要的子系统有一天可能有多个可能的实现时,证明它们的采用是合理的。子系统在这种情况下应该通过接口使用。
通过不合理的方式重复使用需要更多地了解您所覆盖的实施行为,因此存在更大的“耦合”。这就是说,在接口过度消耗的情况下,这也是一种有效的方法。
在Interface vs Composition的特定上下文中,接口引入* more *耦合而不是composition。 – 2012-04-26 14:45:08
我不明白。随意阐述。 – ScrollerBlaster 2012-04-26 14:50:45
问题是关于继承行为。问题是继承是从外部可见的,因此其他人可能会使用它,引入不必要的耦合。另一方面,由于您的属性是隐藏的,因此没有人依赖它们,因此Composition不会引入任何耦合。 – 2012-04-26 15:07:13
您的标题没有意义,而且您的解释有点模糊,所以让我们定义术语(并介绍缺失的关键字)。
有两种不同的东西怎么回事:
- 抽象类V5接口
- 继承VS组成
让我们先从接口和抽象类。
- 一种抽象类(在C++中)是不能被实例化,因为至少有一个其方法是一个纯虚拟方法的类。
- 一个接口是一种没有实现的方法,在C++中它是模拟抽象类只有纯虚拟方法。
因此,在C++的情况下,两者之间没有太大的区别。特别是因为这个区别从来没有考虑到自由功能。
例如,请考虑下面的“接口”:
class LessThanComparable {
public:
virtual ~LessThanComparable() {}
virtual bool less(LessThanComparable const& other) const = 0;
};
你可以平凡扩大它,即使有免费的功能:
inline bool operator<(LessThanComparable const& left, LessThanComparable const& right) {
return left.less(right);
}
inline bool operator>(LessThanComparable const& left, LessThanComparable const& right) {
return right.less(left);
}
inline bool operator<=(LessThanComparable const& left, LessThanComparable const& right) {
return not right.less(left);
}
inline bool operator>=(LessThanComparable const& left, LessThanComparable const& right) {
return not left.less(right);
}
在这种情况下,我们提供的行为......但该类本身仍然是一个接口......哦,好吧。
真正的辩论,因此,是组成继承和之间。
继承经常被误用于继承行为。这不好。应该使用继承来建模is-a的关系。否则,你可能想要组合。
考虑简单的例子:
class DieselEngine { public: void start(); };
现在,我们如何建立与这个Car
?
如果你继承,它将工作。但是,突然间你会得到这样的代码:
void start(DieselEngine& e) { e.start(); }
int main() {
Car car;
start(car);
}
现在,如果你决定WaterEngine
更换DieselEngine
,上述功能不起作用。编译失败。并有WaterEngine
继承DieselEngine
肯定会感到ikky ...
然后是什么解决方案? 组成。
class Car {
public:
void start() { engine.start(); }
private:
DieselEngine engine;
};
这样,没有人可以写一个假设一个汽车发动机荒谬的代码(DOH!)。因此,更换引擎是容易与绝对没有客户影响。
这意味着您的实现和使用它的代码之间的依从性会降低;或者因为它通常被称为:少耦合。
经验法则是,一般情况下,从具有数据或实现行为的类继承应该皱眉。这可能是合法的,但通常有更好的方法。当然,就像所有的经验法则一样,它应该用一粒盐来进行。注意过度工程。
如果类型Y继承自类型X,那么知道如何处理类型X的对象的代码在大多数情况下会自动处理Y类型的对象。同样,如果类型Z实现接口I,那么知道如何使用实现I的对象的代码无需了解任何关于它们的任何信息就能自动使用Z类型的对象。继承和接口的主要目的是允许这样的替换。相反,如果P类型的对象包含Q类型的对象,那么期望与Q类型对象一起工作的代码将无法在P类型中工作(除非P继承自Q持有该类型的对象)。只要P的代码直接将其提供给该代码或使其可用于外部代码,那么期望操作Q类型对象的代码将能够对P中包含的Q实例进行操作。
- 1. C#vs JAVA实例界面
- 2. 构建IronRuby WPF图形用户界面
- 3. 用Tkinter构建图形用户界面
- 4. 流利的界面vs构建模式:优点和缺点
- 5. 自动布局,程序性VS界面构建
- 6. 动态用户界面vs静态用户界面
- 7. 界面转换:界面是地图[字符串]界面{}不是
- 8. Java界面目录结构?
- 9. 构建Android用户界面
- 10. 如何构造界面?
- 11. Django构建登录界面
- 12. 如何重构胖界面?
- 13. 重构:提取界面
- 14. 虚拟vs界面poco,速度更快?
- 15. VS 2010更新界面参考
- 16. Code Vs.界面生成器Iphone
- 17. iOS6 vs iOS7外观界面生成器
- 18. 处理VS/TFS 2012用户界面
- 19. 在Python中开发图形用户界面:Tkinter vs PyQt
- 20. 如何在界面构建器上实现此界面?
- 21. 图形点击界面
- 22. Java图形用户界面
- 23. 图形用户界面
- 24. 图形用户界面
- 25. Web界面或图形UI
- 26. Android界面网页视图
- 27. Zelle图形界面问题
- 28. 图形用户界面 - Tkinter
- 29. 在Android中使用图形构建自定义界面
- 30. 界面构建器中的视图失真。这怎么可能?
您正在考虑使用哪种语言/ – 2012-04-26 13:56:07