14

I have come across prototype inheritance in javascript.

What I wanted to achieve is an outline of methods, which when are inherited must be implemented/defined.

I would like to know if this is possible and if so, how.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
MostWanted
  • 571
  • 1
  • 5
  • 12
  • 1
    Possible duplicate of [How do I create an abstract base class in JavaScript?](http://stackoverflow.com/questions/597769/how-do-i-create-an-abstract-base-class-in-javascript) – faintsignal Jan 10 '17 at 21:49

2 Answers2

26

JavaScript really doesn't have anything like this. As you said, JavaScript is prototype-oriented.


As other answers have said, sure, you can simulate this. But I can't see a good reason to do so. Why do object-oriented programmers use interfaces and abstract classes? Astraction and decoupling. These allow you to do all sorts of nice things, like write methods that consume (take as arguments) and produce (return) values that have abstract types - objects that will at least satisfy some contract regarding its methods and fields.

In turn, we get other "nice things" like compile-time checks for type safety. Try to pass an object of type Foo to a method which only accepts objects of type Bar* and you'll get a compiler warning.

And now for the actual explanations

  1. JavaScript will let you pass any object to any function. What you do with that object inside of the function might cause runtime errors - but nothing will stop you from passing arbitrary arguments, even a different number of arguments than the function declares.
  2. JavaScript variables don't have explicit types. What's the point of "guaranteeing" that some object has some set of methods when you still have to perform manual, explicit type checking?
  3. In JavaScript, functions aren't stuck being subservient to objects — they are first class citizens of the language, and can be used just like objects. So? An object's functions can change at runtime. You can add additional functions to an object, or remove them from an object (or shadow a function in the prototype). So, while you can't really change an object's prototype or constructor after creation (read: new), you can change the object's properties.
  4. Similar to point #2, there is no way to guarantee what a function returns, or even guarantee that a function will return any value at all. Functions don't have an explicitly-declared signature in JavaScript in the way that they do in many OO languages.

What are you actually trying to do?

It sounds like you're trying to impose the relative rigidity of strongly-typed, object-oriented languages onto JavaScript's "relaxed, go-with-the-flow" dynamic type system. IMHO, that's not a great idea. Maybe you could explain the actual problem you're trying to solve?

Sorry if this is long-winded, rant-y, or incoherent. I'm sure there's at least one language out there (OCaml?) that totally throws a wrench in my logic. Throw me some feedback.


*Assuming Foo isn't a subtype of Bar, of course.

...but only at runtime, so it's really no more of a guarantee than what you already get with JavaScript's type system.

thus possibly

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • 2
    +1 for supporting the argument that it might not be a good idea to simulate concepts from strongly typed languages in JavaScript. Moral of the story, dont try to write JavaScript like Java. – Rajat Nov 03 '10 at 00:40
  • I am unsure whether to upvote or downvote. There is something to the argument that javascript uses prototypal inheritence and is dynamic, go with it. And there is something to the argument that there are good things that come from classic java-like OO, so if you want abstract semantics, use them. – hvgotcodes Nov 03 '10 at 14:13
  • @hvgotcodes: IMO, JavaScript is the wrong language to use if you're looking for abstract semantics. There are far better ways to spend time (in any language) than trying to hack in unnatural paradigms. It would be akin to imposing dynamic typing onto Java by using maps as the only object type. _Use the right tool for the job._ – Matt Ball Nov 03 '10 at 14:18
  • @matt have you noticed how a lot of js frameworks like Ext/Sencha and Sproutcore take prototypal JS, and the first thing they do is put machinery in place to mimic classical inheritance? Not to mention that Crockford the king also has code on his website on how to do it? You are arguing that the two paradigms don't mix. I argue that the two can complement each other. Crockford intones that prototypal inheritence can make classical patterns better here: http://www.crockford.com/javascript/inheritance.html – hvgotcodes Nov 03 '10 at 14:25
  • @hvgotcodes: inheritance is a different animal from the Java-like interface/implementation separation that the OP was thinking of. Inheritance is not unnatural or absent from JS! It's just prototype-oriented. – Matt Ball Nov 03 '10 at 14:30
  • @matt, aah right. and JS doesn't support private members, so its a bad idea to simulate them with closure trickery? My point is only that there are cases where you want abstract semantics. it is easy to achieve with JS. its not such a bad idea. – hvgotcodes Nov 03 '10 at 14:34
  • 4
    @hvgotcodes Uh...did you see Crockford's note at the bottom of the article, "I now see my early attempts to support the classical model in JavaScript as a mistake." – Matt Browne Mar 31 '12 at 23:49
9

Javascript doesn't support it out of the box, but it is easy to simulate the desired semantics. If you have a base 'class' that you want to be abstract, put the method(s) that is (are) abstract on it, and have them throw an error. If the user extends your 'class' and does not provide an implementation, the error will be thrown. For example, you can do

function Thing() {...}
Thing.prototype.abstractMethod = function() {
    throw 'You must implement abstractMethod';
}
hvgotcodes
  • 118,147
  • 33
  • 203
  • 236