【发布时间】:2011-05-13 15:50:41
【问题描述】:
在面向对象的编程中,自定义类(如带有姓名数据的 Person 类、地址列表等)保存数据并且也可以包含集合对象。数据结构也用于保存数据。那么,一个类在概念上被认为是高级数据结构吗?在高效系统的设计中(在面向对象的世界和大型系统中),类是否被认为类似于数据结构和算法分析,以实现高效的类设计以提高效率(在 google、facebook 等公司中)?
【问题讨论】:
标签: oop class data-structures
在面向对象的编程中,自定义类(如带有姓名数据的 Person 类、地址列表等)保存数据并且也可以包含集合对象。数据结构也用于保存数据。那么,一个类在概念上被认为是高级数据结构吗?在高效系统的设计中(在面向对象的世界和大型系统中),类是否被认为类似于数据结构和算法分析,以实现高效的类设计以提高效率(在 google、facebook 等公司中)?
【问题讨论】:
标签: oop class data-structures
我建议您阅读Clean Code 第 6 章:对象和数据结构。整章都是关于这个的……不想买书的可以看个摘要,可以找here。
据此,您可以通过两种不同的方式有效地使用类。这种现象称为数据/对象反对称。根据您的目标,您必须决定您的课程是否遵循open/closed principle。
如果它们遵循 OCP,它们将是多态的,并且它们的实例将被用作对象。所以他们将隐藏数据和通用接口的实现,并且很容易添加一个实现该接口的新类型。大多数设计模式都满足 OCP,例如 MVC、IoC、每个包装器、适配器等...
如果它们不遵循 OCP,它们就不会是多态的,它们的实例将被用作数据结构。所以他们会暴露数据,而这些数据将被其他类操作。这也是过程编程的典型方法。有几个不使用 OCP 的示例,例如 DTO、异常、配置对象、visitor pattern 等...
当您应该考虑实现 OCP 并将代码移至较低抽象级别时的典型模式:
class Manipulator {
doSomething(Object dataStructure){
if (dataStructure instanceof MyType1){
// doSomething implementation 1
}
else if (dataStructure instanceof MyType2)
{
// doSomething implementation 2
}
// ...
},
domSomethingElse(Object dataStructure){
if (dataStructure instanceof MyType1){
// domSomethingElse implementation 1
}
else if (dataStructure instanceof MyType2)
{
// domSomethingElse implementation 2
}
// ...
}
}
class MyType1 {}
class MyType2 {}
//if you want to add a new type, every method of the Manipulator will change
修复:将实现移至较低的抽象级别并实现 OCP
interface MyType {
doSomething();
domSomethingElse();
}
class MyType1 implements MyType {
doSomething(){
// doSomething implementation 1
},
domSomethingElse(){
// domSomethingElse implementation 1
}
}
class MyType2 implements MyType {
doSomething(){
// doSomething implementation 2
},
domSomethingElse(){
// domSomethingElse implementation 2
}
}
// the recently added new type
class MyType3 implements MyType {
doSomething(){
// doSomething implementation 3
},
domSomethingElse(){
// domSomethingElse implementation 3
}
}
您应该考虑违反 OCP 并将代码移至更高抽象级别的典型模式:
interface MyType {
doSomething();
domSomethingElse();
//if you want to add a new method here, every class which implements this interface, will be modified
}
class MyType1 implements MyType {
doSomething(){
// doSomething implementation 1
},
domSomethingElse(){
// domSomethingElse implementation 1
}
}
class MyType2 implements MyType {
doSomething(){
// doSomething implementation 2
},
domSomethingElse(){
// domSomethingElse implementation 2
}
}
或
interface MyType {
doSomething();
domSomethingElse();
}
class MyType1 implements MyType {
doSomething(){
// doSomething implementation 1
},
domSomethingElse(){
// domSomethingElse implementation 1
}
}
class MyType2 implements MyType {
doSomething(){
// doSomething implementation 2
},
domSomethingElse(){
// domSomethingElse implementation 2
}
}
//adding a new type by which one or more of the methods are meaningless
class MyType3 implements MyType {
doSomething(){
throw new Exception("Not implemented, because it does not make any sense.");
},
domSomethingElse(){
// domSomethingElse implementation 3
}
}
修复:将实现移至更高的抽象级别并违反 OCP
class Manipulator {
doSomething(Object dataStructure){
if (dataStructure instanceof MyType1){
// doSomething implementation 1
}
else if (dataStructure instanceof MyType2)
{
// doSomething implementation 2
}
// ...
},
domSomethingElse(Object dataStructure){
if (dataStructure instanceof MyType1){
// domSomethingElse implementation 1
}
else if (dataStructure instanceof MyType2)
{
// domSomethingElse implementation 2
}
// ...
},
// the recently added new method
doAnotherThing(Object dataStructure){
if (dataStructure instanceof MyType1){
// doAnotherThing implementation 1
}
else if (dataStructure instanceof MyType2)
{
// doAnotherThing implementation 2
}
// ...
}
}
class MyType1 {}
class MyType2 {}
或将类拆分为子类。
人们通常在方法计数一或二上遵循 OCP,因为重复相同的 if-else 语句不够 DRY。
我不建议您使用部分满足、部分违反 OCP 的混合类,因为这样代码将很难维护。您应该根据每种情况来决定您遵循哪种方法。这通常应该是一个容易的决定,但如果您犯了错误,您仍然可以稍后重构您的代码...
【讨论】:
自定义类是否是数据结构取决于您询问的对象。至少,是的,人们会承认它是一个用户定义的数据结构,它比数组、链表或二叉树等数据结构更特定于领域且更不成熟。对于这个答案,我认为它们是不同的。
虽然将 Big O 算法分析应用于数据结构很容易,但对于类来说则稍微复杂一些,因为它们包装了许多这些结构以及其他类的其他实例......但是对类实例有很多操作可以分解为数据结构上的原始操作并用大 O 表示。作为程序员,您可以通过避免不必要的成员复制并确保方法调用不会经过太多层来努力使您的类更高效.当然,在你的方法中使用高性能算法是不言而喻的,但这不是面向对象编程的。但是,除非必要,否则不应为了性能而牺牲功能、设计和清晰度。而过早的优化就是魔鬼呀呀呀呀呀。
我敢肯定,某处的一些学者已经尝试制定一个量化班级表现的指标,甚至是班级及其运作的微积分,但我还没有遇到过。但是,存在像 this 这样的 QA 研究,它测量项目中类之间的依赖关系……人们可能会争辩说,依赖关系的数量与方法调用的分层之间存在相关性(因此会降低类性能)。但是,如果有人对此进行了研究,我相信您可以找到一个更相关的指标,而无需全面推论。
【讨论】:
我会说概念上一个类NOT是一个数据结构,一个类很好地代表,一个对象的类,对象是抽象的(英文的意思是这个词,而不是这个词的 C++ 或 C# 含义)实体。
我会说类和对象就像实践背后的理论,实践是使用方法和数据实现对象。数据可能很简单,也可能很复杂(所谓的高级数据结构)。
【讨论】:
类只是数据和可以作用于该数据的方法的集合。您可以使用类来实现数据结构,但它们是不同的东西。
以链表为例。您可以使用类来实现链接列表数据结构,在某些语言中,这是最简洁和最明显的方式。这不是实现链接列表的唯一方法,但它可能是最好的,具体取决于语言。
然而,链接列表与成为一个类无关。相反,链接列表是一种将数据表示为单独节点的方式,其中每个节点以某种方式链接到下一个节点。
数据结构是一种对数据建模的概念方法,每个不同的数据结构都有不同的属性和用例。类是某些语言为分组数据和方法提供的一种句法方式。
类通常用于实现数据结构,但说 class== 数据结构是不正确的。
【讨论】:
类描述模型/概念/类型并定义其可能的行为和可能的状态(在您的示例中,Person 可以有名称、地址等。
数据结构是某种类型,可用于以某种方式组织和分组呃……数据。例如,向量和链表是可以用于以有序方式存储数据的数据结构。
您可以拥有一个表示数据结构的类,例如 C++ 中的 std::vector 或 Java 中的 java.util.ArrayList。
【讨论】:
简单地说,一个类可以被看作是一种由给定编程语言(比如Java)提供的语法工具,它将数据和方法捆绑在一起,用于在程序中实现概念或对象或应用程序。
通过类,您可以实现一个软件组件,该组件代表现实世界中的想法或对象。为此,您可以将对象的属性捕获为成员变量,并将其行为或操作捕获为类的方法。
另一方面,数据结构基本上是处理数据的模型(数组、链表、二叉搜索树)。类通常用于实现数据结构,因为它们以独特的方式捕获这些结构的状态和行为。
因此在这个意义上两者是不同的。
【讨论】: