0

Does polymorphism apply only to OOP concept in JavaScript? I am trying to use object composition vs prototypal/class inheritance in JavaScript. What would be the implementation of polymorphism in object composition if the concept applies?

Here is an example of prototypal inheritance with the implementation of polymorphism (method overriding , reimplementing render method at the child object)

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());
4
  • 1
    please add an example, what you like to get (and what not work ...)? Commented Oct 10, 2018 at 8:33
  • 1
    That is… somewhat vague and broad… If you compose your object, and you do this.foo.bar(), then the specific behaviour obviously varies with what foo is, which you can influence by passing foo as an argument when composing your object, so that'd be a pretty simple example of polymorphism. Commented Oct 10, 2018 at 8:35
  • @NinaScholz edited with the example Commented Oct 10, 2018 at 10:40
  • @deceze edited with the example Commented Oct 10, 2018 at 10:41

1 Answer 1

2

It is actually hard to talk about polymorphism in JavaScript, because Wikipedia defines polymorphism as:

Polymorphism [...] is the provision of a single interface to entities of different types[1] or the use of a single symbol to represent multiple different types.[2]

As there are only the primitive types and "objects", it is difficult to talk about types of these objects. One could say there are other types because of the prototype chains and the instanceof operator, one could also say that javascript got duck typing. Take the following example:

 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

Now which one is of type User? is there a user type? There is no right or wrong, just opinion. The following is my opinion on it:

Does polymorphism apply only to OOP concept in JavaScript?

I'd say No. The paradigm is the "style to write certain things", and polymorphism is a way to describe the relationship of objects, you can use objects in all paradigms.

What would be the implementation of polymorphism in object composition if the concept applies?

If we got two factories, lets say user and reader they could look like:

 function createUser() {
   return { name: "test" };
 }

 function createReader() {
   return { books: ["a book"] };
 }

 const user = createUser(), reader = createReader();

Now then we can get polymorphism in multiple ways:

1) row polymorphism

1a) We could turn the user into a reader by adding books:

 user.books = ["another book"];

Now user is a reader as it has books (thats the Duck test)

1b) We could combine a user and a reader:

const readingUser = Object.assign(createUser(), createReader());

2) subtyping

A reader could always be a user if we change the constructor to:

 function createReader() {
   return { ...createUser(), books: ["a book"] };
 }

now every reader is a user, we got inheritance (however no classical inheritance).

3) ad hoc polymorphism

We could declare functions that behave diffferently for users or readers:

 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) parametric polymorphism

Both readers and users are objects, so we can just work with them "as objects":

 Object.freeze(reader);
 Object.freeze(user);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.