一尘不染

OOP的学校有哪些?

java

Smalltalk OOP和Simula OOP之间在哲学上有区别吗?

这是一个与Java&C#与C 间接相关的问题。据我了解,C 基于Simula,但是Java和C#或多或少地来自Smalltalk系列。


阅读 191

收藏
2020-12-03

共1个答案

一尘不染

在更广泛的OOP标语中有几个“风格”上的关键“差异”。

在所有情况下,关于 静态动态
类型系统的声明主要意味着一个或另一个,这个问题远非明确或明确定义的。同样,许多语言选择模糊选择之间的界限,因此无论如何这都不是二进制选择的列表。

多态后期绑定

或“什么foo.Bar(x)意思?”

  1. 类型的层次结构被扁平化为每个实例的特定实现(通常通过vtable完成),并且通常允许显式引用基类实现。
    • 从概念上讲,您将查看foo在呼叫站点处的最特定类型。如果对调用的参数x具有Bar的实现,则如果不选择foo的父级,则重复该过程。
    • 示例:C ++ / Java / C#, 经常使用“ Simula style ”。
  2. 纯消息传递。要求foo中处理名为“ Bar”的消息的代码接受x。仅名称很重要,而呼叫站点可能对Bar的确切含义没有任何假设。与以前的方法(其中所讨论的方法为Bar)相反,已知该方法是在编译时定义的关于类型层次结构的任何已知知识上定义的东西(尽管层次结构中的确切位置将保留到运行时)。

1通常在错误的静态类型框架中使用,在编译时检查是否存在这样的实现。此外,如果x和y是不同类型,则语言通常会区分Bar(x)和Bar(y)。这是方法重载,并且具有相同名称的结果方法被视为完全不同。

2通常在动态语言中使用(这往往会避免方法重载),因此,在运行时foo类型的消息可能没有名为“ Bar”的消息的“
handler”,因此不同的语言会以不同的方式进行处理。

如果需要,两者都可以以相同的方式在后台实现(第二种默认情况下,Smalltalk风格的默认设置是调用一个函数,但这并不是在所有情况下都具有定义的行为)。由于前一种方法可以很容易地实现为简单的指针偏移函数调用,因此可以更轻松地使其相对较快。这并不意味着其他样式也不能快速制作,但是可能需要做更多的工作才能确保在这样做时不会损害更大的灵活性。

继承/重用

或“婴儿从哪里来?”

  1. 基于类
    • 方法实现被组织为称为类的组。当需要实现继承时,定义一个 扩展 父类的类。这样,它获得了父级的 所有 公开方面(包括字段和方法),并且可以选择更改某些/全部方面,但 不能 删除任何方面。您可以添加和更新,但不能删除。
    • 示例:C ++ / Java / C#(请注意,SmallTalk和Simula都使用此方法)
  2. 基于原型
    • 对象的任何实例都只是一组已标识方法(通常由名称标识)和状态(以再次命名)的形式的集合。每当需要这种“类型”的新实例时,都可以使用现有实例来克隆新实例。这个新类保留了上一类的状态和方法的副本,但可以对其进行修改以删除,添加或更改现有的命名字段和方法。
    • 示例:Self / JavaScript

同样,静态语言倾向于1,动态语言倾向于2,尽管这绝不是要求它们简单地适应样式。

基于接口或类

或“什么或如何?”

  1. 接口列出了所需的方法。他们是合同
    • 范例:VB6
  2. 类列出了必需的方法,但可以选择提供其实现
    • 示例:Simula

这绝不是二进制选择。大多数基于类的语言都允许使用抽象方法的概念(尚未实现的方法)。如果您有一个所有方法都是抽象的类(在C
++中称为纯虚函数),则该类相当于一个接口,尽管它可能也定义了一些状态(字段)。真正的接口应该没有状态(因为它 定义可能的事物,而不是其发生的方式。

只有较旧的OOP语言趋向于仅依赖一种或另一种。
VB6仅在接口上,没有实现继承。
Simula使您可以声明纯虚拟类,但可以实例化它们(使用时会出现运行时错误)

单继承或多继承

或“谁是爸爸?”

    • 只有一种类型可以是另一种类型的父项。在上面的基于类的表单中,您只能扩展一种类型(从中获取实现)。通常,此形式包括接口的概念,作为该语言的一流方面。
    • 优点包括更清晰的元数据和自省,更简单的语言规则。
    • 复杂性包括难以将有用的方法引入范围(MixInsExtension方法之类的方法旨在缓解此类问题)
    • 示例:C#/ java
  1. 多个-您可以扩展多个类
    • 优点包括某些结构更易于建模和设计
    • 复杂性包括解决冲突的复杂规则,尤其是当存在可以采用任何父类型的重载方法时。
    • 示例:C ++ / Eiffel

这个问题引起了广泛的争论,特别是因为它是C ++的OOP实现与许多现代的静态类型语言(如c#和java之类的继任者)之间的关键区别。

变异性

或“您想对我做什么?”

  1. 可变的
    • 对象一旦创建,即可更改其状态。
  2. 不变的
    • 对象一旦创建就无法更改。

通常,这不是全部或全部,它仅仅是一个默认值(最常用的OOP语言默认情况下默认为可变)。这会对语言的结构产生很大影响。许多包含OOP功能的主要功能语言会将对象默认为不可变状态。

他们的OOP的“纯正”

或“所有事物都是对象吗?”

  1. 绝对将系统中的所有内容都视为一个对象(甚至可能是方法本身,它们仅仅是另一种对象,并且可以与其他对象相同的方式进行交互)。
    • 示例:SmallTalk
  2. 并非所有事物都是对象,您无法将消息传递给所有事物(尽管系统可能会跳成一圈以使其看起来像您可以)
    • 示例:C ++ / C#/ Java(请参阅注释*)

这是非常复杂的,因为像自动装箱这样的技术使一切看起来都很好,但是您会发现存在一些边界情况,在这些情况下发现了这种“编译器魔术”,并且在幕后发现了Oz众所周知的向导,从而导致了问题或错误。
。在具有默认不变性的语言中,这种情况不太可能发生,因为对象的关键方面(它们既包含方法又包含 状态 )意味着与对象相似但不太复杂的事物。

  • 对于Java / C#,自动装箱(或在c#中)系统使您可以在 语法上将 任何变量都视为对象,但实际上并非如此,这在尝​​试锁定自动装箱的区域中表现出对象(被编译器拒绝,因为这将是一个明显的错误)。

静态或动态

或“您认为自己是谁?”

语言设计的一个更为广泛的方面,不是一个要深入的方面,而是此决策中固有的选择影响了OOP的许多方面,如前所述。

多态后期绑定的各个方面可以取决于:

  • 消息传递到的对象的类型(在编译时/运行时)
  • 类型参数( 小号 ),其被传递(在编译时间/运行时间)

语言变得越动态,这些决策就越趋于复杂,但是相反,语言用户的投入越多,而不是语言 设计者
在决策中的投入越大。在这里举一些例子是很困难的,因为可以将静态类型的语言修改为包括动态方面(例如c#4.0)。

2020-12-03