基于原型的对象导向。好的,不好的和丑陋的呢?
我来自基于类的面向对象语言,最近我一直在学习那些花哨的动态语言(JavaScript、Python 和 Lua),我想知道在这些语言中如何使用面向对象编程。了解此方法的缺点和问题以及与传统面向对象的优势将会很有用。
我的一般理解是:基于原型的面向对象编程基本上是与对象一起编程,但没有关于如何使用它们的标准,而在普通的面向对象编程中,有一个固定的预定义方式来创建和使用对象。
总之,这种方法的好处、坏处和丑陋的部分是什么?
原文链接 https://stackoverflow.com/questions/385403
为了保护带宽,这里提供了链接来查看我的回答:“如何在JavaScript中模拟‘类’?(使用或不使用第三方库)” ,它包含进一步的参考和实例。
简短的回答是:JavaScript原型对象(OO)的核心是委派。在这种面向对象编程(OOP)模式中,相同“类”的不同对象可以将方法和属性的处理委派给相同的原型(通常是一些第三方对象):
var foo = {
property: 42,
inc: function(){
++this.counter;
},
dec: function(){
--this.counter;
}
};
// 注意:foo没有定义“counter”。
让我们创建一个构造函数,它的原型是foo。实际上,未处理的所有内容都将委派给foo。
var Bar = function(){
this.counter = 0;
};
Bar.prototype = foo; // 这就是我们设置委派的方式。
// 有些人将Bar(构造函数)称为“类”。
var bar = new Bar();
console.log(bar.counter); // 0 --- 来自bar自身
console.log(bar.property); // 42 --- 没有在bar中定义,在foo中定义
bar.inc(); // 在bar中未定义 => 委托给foo
bar.inc();
bar.dec(); // 在bar中未定义 => 委托给foo
// 注意:foo.inc()和foo.dec()调用,但this === bar,
// 这就是bar被修改,而不是foo。
console.log(bar.counter); // 1 --- 来自bar自身
让我们在bar上直接定义inc()
:
bar.inc = function(){
this.counter = 42;
};
bar.inc(); // 在bar中定义 => 直接调用它。
// 甚至foo.inc()都未被调用。
console.log(bar.counter); // 42 --- 来自bar
设置单一继承链:
var Baz = function(){
this.counter = 99;
};
Baz.protype = new Bar();
var baz = new Baz();
console.log(baz.counter); // 99
baz.inc();
console.log(baz.counter); // 100
console.log(baz instanceof Baz); // true
console.log(baz instanceof Bar); // true
console.log(baz instanceof Object); // true
很好吧,对吧?
Prototype-based OO 不太适合静态类型检查,有些人可能会认为这是坏的或丑陋的。Prototype-based OO _有_一种创建新对象的标准方法,你可以克隆和修改现有的对象,也可以构建工厂等。
我认为人们最喜欢的(“好的”)是基于原型的 OO 非常轻量级和灵活,提供了非常高的功率与重量比。
关于如何使用基于原型的 OO 的提示,一个很好的起点是原始 Self 论文上的 简单之力。
经典继承在灵活性方面存在缺陷,因为我们要说“这个对象属于这种类型,没有其他类型”。有些语言引入多重继承以减轻这种问题,但多重继承也有其自身的问题,因此在继承方面,纯组合优于继承的好处变得明显(在静态类型语言中,它是一种运行时而不是编译时机制)。
将组合概念推展到“纯净”程度,我们可以完全消除经典继承和静态类型。通过在运行时组合对象并将其用作蓝图(原型方法),我们不必通过继承过度约束对象,并且也不必担心多重继承方法固有的问题。
因此,原型方法意味着模块的开发变得更加灵活。
当然,说没有静态类型就容易开发是另一回事。在我看来,这是不可能的。
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
- 如何创建一个 lua 脚本以针对特定键为 fluentbit 进行限流
原型模型的类
首先,实际上原型模型并不是很不同。Smalltalk 使用一种类似的方案,即将类看作是一个具备类方法的对象。
从类的角度来看,一个类实际上是具有相同数据和方法的对象等价类。将方法添加到原型中可以看作是创建一个新的子类。
这种实现方式简单,但很难有效地进行类型检查。