是Smalltalk的面向对象和面向对象的Simula的存在之间的哲学分歧?
这是与Java和C#VS C ++间接的问题。 据我所知,C ++是基于Simula的,但Java和C#是从Smalltalk的家庭或多或少。
是Smalltalk的面向对象和面向对象的Simula的存在之间的哲学分歧?
这是与Java和C#VS C ++间接的问题。 据我所知,C ++是基于Simula的,但Java和C#是从Smalltalk的家庭或多或少。
几个关键的风格‘更广泛的面向对象的横幅中的“在差异’。
在所有的情况下,关于静态或动态类型系统语句的意思主要是一个或另一个,这个问题还远远没有明确的或明确的规定。 也有许多语言中选择模糊的选择之间的界限,所以这是不以任何方式二进制选项列表。
或“什么foo.Bar(x)
是什么意思?”
1通常静态类型框架,其中它是一个错误,在编译时检查内用于向不存在这样的实施方式。 此外,该语言常常栏(x)和酒吧(Y)之间进行区分,如果x和y是不同的类型。 这是方法重载和具有相同的名称所产生的方法被视为完全不同。
2通常用在动态语言(其倾向于避免方法重载),为这样的有可能的是,在运行时foo的类型已经为名为“酒吧”消息没有“处理”,不同的语言以不同的方式处理这种使用。
两者都可以在幕后以同样的方式,如果需要,可以实现(通常为第二默认,Smalltalk的风格是调用一个函数,但这不是由在所有情况下定义的行为)。 由于前一种方法常常可以很容易地为简单的指针偏移功能实现调用它可以更容易地做出比较快的。 这并不意味着其他样式也无法快速做出,但更多的工作可能需要确保这样做时具有更大的灵活性不会受到损害。
或者“哪里的婴儿是从哪里来的?”
1再次趋于动态静态语言的情况发生,2虽然这绝不是他们只是借给自己的风格要求。
或“什么或怎么样?”
这是非常不二元选择。 大多数基于类的语言允许的抽象方法的概念(那些没有实现还)。 如果你有一个类,所有方法都是抽象的(称为纯虚的C ++)类的数额是那什么非常的界面,尽管一个可能还定义了一些状态(字段)。 一个真正的接口应该没有状态(因为它仅仅定义了什么是可能的,它不是如何发生的。
只有较早OOP语言倾向于仅仅依靠一种或另一种。
VB6只有在接口上,并没有实现继承。
西穆拉让你声明纯虚类,但你可以实例化它们(与使用运行时错误)
或者“谁是爸爸?”
这个问题引发相当大的争议,特别是因为它是C ++的面向对象的实现和许多人认为像C#和Java可能接班人现代静态类型语言之间的关键区别。
或者“你想要做什么给我?”
通常这不是一个全有或全无它只是一个默认的(最常用的OOP语言默认为可变默认)。 这可能对语言的结构如何影响很大。 其中包括一些OOP许多主要功能的语言功能默认的对象有不可改变的状态。
或“一切都对象?”
这是很复杂的,因为像元的自动装箱技巧使它看起来好像一切是,但你会发现,存在一些边界情况下,这个“编译器魔法”被发现并奥兹的谚语向导发现背后产生的窗帘是问题或错误。 在与不变性作为默认语言,这是不太可能发生,因为对象的关键方面(它们同时包含方法和状态 )意味着事情相类似的对象,但不太具有并发症少等优点可能性。
或者“你认为谁你是谁?”
语言设计的一个更为普遍的方面,而不是一个进入这里,但正如前面所提到的这个决定所固有的选择影响OOP的许多方面。
多态后期绑定可以依靠的只是几个方面:
更具活力的语言变得更复杂的这些决定往往成为但反过来更多的输入语言的用户,而不是语言设计者的决定。 这里给出的例子是一些什么鲁莽,因为静态类型语言可以被修改为包括动态方面(如C#4.0)。
我把Java和C#中的Simula的阵营,以及:
Smalltalk中,被动态类型,是撇开你引用其他四种语言。
Smalltalk是结构类型(别名鸭打字),而其他四个名义上类型。
(什么Java和C#有与Smalltalk中共同被主要是基于虚拟机,但在编程风格的影响小)。
Java和C#是绝对不会从Smalltalk的家庭。 阿兰凯甚至说,当他创造了OOP他没有考虑到如Java或C ++东西。 的Java,C#和C ++的所有解释OOP在几乎相同的方式。
如Smalltalk和Ruby语言有一个基于消息传递一种完全不同的模式。 在C ++类实质上命名空间的方法和状态。 方法调用是在编译时绑定。 Smalltalk的不结合“方法调用”,直到运行时。 这样做的结果是,在C ++中
foo->bar
编译意味着“调用foo的对象上的杆法。” 如果酒吧是不虚的,我想像的杆法的地址是专门引用。
在Smalltalk
foo bar
的意思是“发送消息栏foo的对象”。 foo
可以做任何它想要与该消息时到达。 默认行为是要调用的方法命名的bar
,但不是必需的。 这家酒店在Ruby中利用ActiveRecord的列存取。 当你有一个ActiveRecord对象,你发送一个列的名称在其数据库中的表作为消息,如果没有与定义的名称的方法,检查是否有在桌子上,如果一列由名有返回值。
消息传递看起来像一个微小的,无关紧要的细节,但出来的,面向对象的其余部分容易流动。
“OOP对我来说意味着只有消息,当地保留和保护,国家进程的隐藏,和极端后期绑定的所有的东西,它可以在Smalltalk和LISP来完成。有可能是其他系统中,这是可能的,但我不知道他们。” - 艾伦凯,Smalltalk的创造者
埃菲尔铁塔是一种静态类型,编译,多重继承纯OOP语言。
http://dev.eiffel.com
现代的(我用这个词轻轻地)面向对象的编程语言Objective C中是最为如Smalltalk。
在C ++,C#和Java:消息在编译时绑定。
作为消息被发送到对象,你能想到一个方法调用。
在目标C,Smalltalk中:消息在运行时约束。
我想说的静态类型和动态类型的面向对象是面向对象的同一所学校内的两个独立的学科。
的Java,C#和C ++都遵循类似的面向对象的策略。 它是基于在编译时绑定函数调用。 根据ONT他打电话,当编译发生或者对冲到虚函数表的直接函数调用或者是固定的。 相比之下Smalltalk的面向对象是基于消息传递。 从概念上讲每个方法调用是一条消息,询问是否有一个称为方法接收对象为“foo”。
Smalltalk中没有任何的接口概念。 它不仅具有外观类似的方法。 在C ++组的语言,一切都与接口绑定。 一个无法实现AddRef和还没有实现的QueryInterface版本(即使它只是一个存根),因为它们IUnknown接口的一部分。 在Smalltalk中,没有任何的IUnknown。 只有3个功能,其中任何一个可以实施与否的集合。
我想说的也有相当大的差异,在概念上,基于类的OOP(其中Smalltalk中,西穆拉,C#和Java是所有的例子),并基于原型的OOP(从而拉开了自我,是最普遍的在JavaScript)之间。
除了上述点外,还有相对于Smalltalk的西穆拉的概念击穿。
从概念上讲,“Smalltalk风格”典型地表示当被称为消息在运行时确定的方法运行,辅助多态性。
“西穆拉式”,而另一方面,通常似乎表明,所有的方法调用都是真的写重载函数的一种简便的方法调用 - 没有运行时多态性。 (如果我错了,请大家指正。)
在中间,我们有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;
}