多态性仅适用于JavaScript中的OOP概念吗?我正在尝试在JavaScript中使用对象组合与原型/类继承。如果适用该概念,那么在对象组合中多态性的实现将是什么?
以下是通过多态实现(方法覆盖,在子对象上重新实现render
方法)的原型继承的示例
function HtmlElement() {
this.click = function() {
console.log('clicked');
}
}
HtmlElement.prototype.focus = function(){
console.log('focued');
}
function HtmlSelectElement(items = []) {
this.items = items;
this.addItem = function(item) {
this.items.push(item);
}
this.removeItem = function(item) {
this.items.splice(this.items.indexOf(item), 1);
}
this.render = function() {
return `
<select>${this.items.map(item => `
<option>${item}</option>`).join('')}
</select>`;
}
}
HtmlSelectElement.prototype = new HtmlElement();
HtmlSelectElement.prototype.constructor = HtmlSelectElement;
function HtmlImageElement(src) {
this.src = src;
this.render = function() {
return `<img src="${this.src}" />`
}
}
HtmlImageElement.prototype = new HtmlElement();
HtmlImageElement.prototype.constructor = HtmlImageElement;
const elements = [
new HtmlSelectElement([1, 2, 3]),
new HtmlImageElement('http://')
];
for (let element of elements)
console.log(element.render());
答案 0 :(得分:2)
实际上很难谈论JavaScript中的多态性,因为Wikipedia defines polymorphism as:
多态[...]是为不同类型的实体提供单个接口[1]或使用单个符号表示多种不同类型。[2]
由于只有原始类型和“对象”,因此很难谈论这些对象的类型。由于原型链和instanceof
运算符,人们可能会说还有其他类型,人们也可能会说javascript进行了鸭子输入。请看以下示例:
class User {
constructor() { this.name = "test"; }
}
value | type | instanceof User | "name" in
-----------------------------------------------------------------------------------
new User() | object | true | true
{ name: "test" } | object | false | true
{} | object | false | false
现在,哪一个属于用户类型?有用户类型吗?没有对与错,只有意见。以下是我对此的看法:
多态性仅适用于JavaScript中的OOP概念吗?
我要说不。范式是“写某些东西的样式”,而多态是描述对象之间关系的一种方式,您可以在所有范式中使用对象。
如果适用该概念,那么在对象组合中多态性的实现将是什么?
如果我们有两个工厂,假设user
和reader
看起来像:
function createUser() {
return { name: "test" };
}
function createReader() {
return { books: ["a book"] };
}
const user = createUser(), reader = createReader();
现在,我们可以通过多种方式获得多态性:
1)行多态性
1a)通过添加书籍,我们可以将用户变成读者:
user.books = ["another book"];
现在 user 是阅读器,因为它具有 books (即Duck test)
1b)我们可以结合一个用户和一个读者:
const readingUser = Object.assign(createUser(), createReader());
2)分型
如果我们将构造函数更改为:读者可以永远是用户
function createReader() {
return { ...createUser(), books: ["a book"] };
}
现在每个读者都是用户,我们得到了继承(但是没有经典继承)。
3)临时多态性
我们可以声明对于用户或读者而言行为不同的函数:
function doSomething(obj) {
if(obj.name) {
console.log("a user");
}
if(obj.books) {
console.log("a reader");
}
}
doSomething(user); // a user
doSomething(reader) // a reader
doSomething(readingUser); // a user, a reader
4)参数多态性
读者和用户都是对象,因此我们可以将它们“作为对象”使用:
Object.freeze(reader);
Object.freeze(user);