OOP的学校是什么?

时间:2009-07-17 15:25:44

标签: c# java c++ oop

Smalltalk OOP和Simula OOP之间是否存在哲学差异?

这是一个与Java& C#与C ++间接的。据我所知,C ++基于Simula,但Java和C#或多或少来自Smalltalk家族。

9 个答案:

答案 0 :(得分:63)

答案 1 :(得分:6)

我也把Java和C#放在Simula阵营中:

  • 动态打字的Smalltalk与你引用的其他四种语言完全不同。

  • Smalltalk是结构类型(别名鸭子打字),而其他四个名义上是打字。

(Java和C#与Smalltalk的共同点主要是基于VM,但对编程风格影响不大)。

答案 2 :(得分:4)

Java和C#绝对不是来自Smalltalk家族。 Alan Kay甚至说,当他创建OOP时,他没有考虑Java或C ++之类的东西。 Java,C#和C ++都以完全相同的方式解释OOP。

像Smalltalk和Ruby这样的语言有一个完全不同的模型,它基于消息传递。在C ++中,类本质上是方法和状态的名称空间。方法调用在编译时绑定。 Smalltalk直到运行时才绑定“方法调用”。结果是在C ++中

foo->bar
编译

表示“在foo对象上调用bar方法”。如果bar是非虚拟的,我想是专门引用bar方法的地址。

在Smalltalk中

foo bar

表示“将消息栏发送到foo对象”。 foo可以在收到此消息后随心所欲地执行任何操作。默认行为是调用名为bar的方法,但这不是必需的。此属性在Ruby中用于ActiveRecord列访问器。当您有一个ActiveRecord对象并将其数据库表中的列名称作为消息发送时,如果没有定义该名称的方法,它会检查表中是否有该列的列,如果返回值。

消息传递可能看起来像一个微小的,无关紧要的细节,但除此之外,OOP的其余部分很容易流动。

“OOP对我来说只意味着消息传递,本地保留和保护以及状态进程的隐藏,以及所有事物的极端后期绑定。它可以在Smalltalk和LISP中完成。可能还有其他系统,这是可能,但我不知道他们。“ - Smalltalk的创建者Alan Kay

答案 3 :(得分:4)

Eiffel是一种静态类型,编译,多继承的纯OOP语言。

http://dev.eiffel.com

答案 4 :(得分:3)

现代(我轻易使用术语)OO编程语言Objective C最像是smalltalk。

Messaages:

在C ++,C#和Java中:消息在编译时绑定 您可以将方法调用视为发送给对象的消息。

在Objective C中,Smalltalk:消息在运行时绑定。

答案 5 :(得分:2)

我认为静态类型和动态类型的OOP是同一OOP学校中的两个独立学科。

答案 6 :(得分:2)

Java,C#和C ++都遵循类似的OOP策略。它基于在编译时绑定的函数调用。根据他的调用,当编译发生时,直接函数调用或vtable中的偏移量是固定的。相比之下,Smalltalk的OOP基于消息传递。从概念上讲,每个方法调用都是一个消息给接收对象,询问它是否有一个名为“Foo”的方法。

Smalltalk没有接口的概念。它只有类似的方法。在C ++语言组中,一切都绑定到接口。如果没有实现QueryInterface(即使它只是一个存根),也无法实现AddRef和Release,因为它们都是IUnknown接口的一部分。在Smalltalk中,没有IUnknown。只有3个函数的集合,其中任何一个都可以实现。

答案 7 :(得分:2)

我认为在概念上,基于类的OOP(其中Smalltalk,Simula,C#和Java都是示例)和基于原型的OOP(以Self开头并且最为普遍)之间存在着非常大的差异。在JavaScript中)。

答案 8 :(得分:1)

除上述观点外,还有Smalltalk与Simula的概念分析。

从概念上讲,“Smalltalk-style”通常表示在调用消息时运行的方法是在运行时确定的,这有助于实现多态性。

另一方面,“Simula-style”通常似乎表明所有方法调用实际上只是编写重载函数调用的便捷方式 - 没有运行时多态性。 (如果我错了,请纠正我。)

在中间,我们有Java:默认情况下所有方法都是虚拟的,但是静态类型并且具有编译时类型调度。

示例:

// C++
class Base {
  void doSomething() {
    cout << "Base::doSomething() called!\n";
  }
}
class Derived : Base {
  void doSomething() {
     cout << "Derived::doSomething() called!\n";
  }
}
int main() {
  Base* b = new Base();
  Derived* d = new Derived();
  b->doSomething(); // prints "Base::doSomething() called!"
  d->doSomething(); // prints "Derived::doSomething() called!"
  Base* d2 = d;     // OK; Liskov substitution principle.
  d2->doSomething(); // prints "Base::doSomething called!"  (!)
  delete b;
  delete d;
  return 0;
}

VS

// Objective-C
//Base.h
@interface Base
{
}
-(void)doSomething
@end
//Base.m
#import "Base.h"
@implementation Base
-(void) doSomething {
  printf("doSomething sent to Base!");
}
@end
//Derived.h
#import "Base.h"
#import "Base.m"
@interface Derived : Base
{
}
@end
//Derived.m
#import "Derived.h"
@implementation Derived
-(void) doSomething {
  printf("doSomething sent to Derived!")
}
@end

//Main.m
#import "Base.h"
#import "Base.m"
#import "Derived.h"
#import "Derived.m"
int main() {
  Base* b = [[Base alloc] init];
  Derived* d = [[Derived alloc] init];
  [b doSomething]; // prints "doSomething sent to Base!"
  [d doSomething]; // prints "doSomething sent to Derived!"
  Base* d2 = d;
  [d2 doSomething]; // prints "doSomething sent to Derived!"
  [b release];
  [d release];
  return 0;
}