In Javascript, in contrast to other languages which OOP like Java, do not provide interfaces. There is some solutions on the internet which are more complex than mine, but I want to share with you my way how to resolve this problem, to get some constructive critisism from you and check if I choose the right way of thinking. I choose Answer your own question – share your knowledge, Q&A-style and you will see my answer below.
-
It is still a runtime exception and only occurs when you actually call the method on an instance. You can't implement multiple interfaces either. Maybe a compile to language like typescript, dart or closure compiler would be a better solution. Or something like a mix in pattern that has a timeout checking for the target implementing the needed functions (still a runtime error but no need to create an instance and call the function first) – HMR Sep 13 '14 at 09:44
-
@HMR could you tell more about this error, how to reproduce it with my code below? Because I didn't get any exceptions. – Radek Anuszewski Sep 13 '14 at 16:21
2 Answers
Here is an example that uses a timeout to check if the needed functions are implemented, you can implement multiple Interfaces.
Since JS is not a compile time type checked language you can't really have a good solution for this. Maybe you can have a look at mix ins (under mix ins), leave the default implementation or override.
function PersonInterface(proto,fnName){
//after running the implements function it depends how quickly you're
// creating instances and how quickly you implement the functions
setTimeout(function(){
if(typeof proto.getSurName !== 'function'){
throw new Error(fnName + ' has to implement getSurName');
}
//and others if needed
},100);
}
function implements(fn, implements,fnName){
implements(fn.prototype,fnName);
}
function Employer(){};
implements(Employer, PersonInterface,'Employer');
//depends how quickly you set the getSurName
// and how quickly you will be creating Emplyer instances
// trying to call getSurName
// comment out the next line and you'll get
// Employer has to implement getSurName
Employer.prototype.getSurName=function(){};
My solution based on Javascript Prototype. I create a class which acts like interface by throwing Error object in methods which should be implemented, when child inherits from interface. Let's create PersonInterface:
function PersonInterface(){
}
PersonInterface.prototype.getName = function(){
throw typeof(Error) !== 'undefined'?
new Error(" Interface Person: method getName() unimplemented!")
: " Interface Person: method getName() unimplemented!";
};
PersonInterface.prototype.getSurname = function(){
throw typeof(Error) !== 'undefined'?
new Error(" Interface Person: method getSurname() unimplemented!")
: " Interface Person: method getSurname() unimplemented!";
};
Then let's create a Customer, which implements PersonInterface interface:
function Customer(name, surname){
PersonInterface.call(this);
this.__name = name;
this.__surname = surname;
}
Customer.prototype = Object.create(PersonInterface.prototype);
Customer.prototype.getName = function(){
return this.__name;
};
Customer.prototype.getSurname = function(){
return this.__surname;
};
When getName() or getSurname() function are not implemented, it throws an Error object with corresponding message. I create a JSFiddle which demonstrates how it works: Javascript Interface with Prototype (click)
When you, for example, remove getSurname() method from Customer's prototype, it throws an Error - which you find in your browser console. I know that is simple solution and on the net we can find many solutions, but I think it can resolve problem when we don't need something more complex than simple interface.

- 1,812
- 8
- 34
- 62
-
1First of all, you are implementing an abstract base class not an interface. Interfaces shouldn't define any methods and in particular should not not define a constructor (so no need to call the PersonInterface constructor in the Custumer constructor) – hugomg Sep 13 '14 at 09:30
-
Secondly, double underscore is a bit overkill. In javascript people usually don't bother with underscores or use a single one as the convention to mark a field as non-public. – hugomg Sep 13 '14 at 09:31
-
Finally, if all you want is an *interface" then you might not need to create a parent class at all. Javascript is dynamically typed so you can use duck typing instead: just create a new class that implements a getName and a getSurname method and it will instantly implement the person "interface". – hugomg Sep 13 '14 at 09:32