2

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.

Radek Anuszewski
  • 1,812
  • 8
  • 34
  • 62
  • 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 Answers2

1

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(){};
Community
  • 1
  • 1
HMR
  • 37,593
  • 24
  • 91
  • 160
0

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.

Radek Anuszewski
  • 1,812
  • 8
  • 34
  • 62
  • 1
    First 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