Question

Usually on Php or in Java and in other single Inheritance Object Oriented Languages, when I am writing a software I use and Interface then and afterwards I implement the class that implements the business logic.

For example let us suppose we have a File Uploader that allow us to Upload into various ways in our case into an FtpServer or into an AmazonS3 Bucket.

Therefore I declare an interface FileUploaderInterface

interface FileUploaderInterface 
{
   public function addFile(fromPath,toPath);
   public function removeFile(path);
}

And afterwards I Implement a seperate fileUploader for each seperate way we want to upload the data:

eg. for Ftp

class FtpFileUploader implements  FileUploaderInterface
{
   public function addFile(fromPath,toPath)
   {
     //Implement Method
   }
   public function removeFile(path)
   {
     //Implement Method
   }
}

eg. And for Amazon S3

class AmazonS3FileUploader implements FileUploaderInterface
{
   public function addFile(fromPath,toPath)
   {
     //Implement Method
   }
   public function removeFile(path)
   {
     //Implement Method
   }
}

With that I have the flexibility to have a Unique Handling for the file uploads regardless how the Upload Mechanism itself will work so if I want to upload using an X api I just have to implement the FileUploaderInterface Interface.

But on ES6 I find a it myself like a fish out of water int terms of software desighn so it it a good idea/practice to declare a class that has all the basic methods it want that plays the role of an interface

eg: A generic class for file Uploading in a file named 'FileUploader.js'

export default class FileManager {

  addFile(fromPath,toPath,callback){

  }


  deleteFile(path, callback){

  }
 }

And for each way for uploading I just develop a specific class:

eg. For Uploading via FTP

import FileManager from './FileUploader.js'

export default class FtpUploadManager extends FileManager {

  addFile(fromPath,toPath,callback){
    // Implement method
  }


  deleteFile(path, callback){
    // Implement method
  }
}

eg. For uploading via Amazon S3

import FileManager from './FileUploader.js'

export default class S3UploadManager extends FileManager {

  addFile(fromPath,toPath,callback){
    // Implement method
  }


  deleteFile(path, callback){
    // Implement method
  }
}

What are the pos and cons of using the following method?

The main difference I am asking of Are there any OO-principles that are practically applicable for Javascript? is if a specific way of using Js Classes is good or not and not a generic one.

Was it helpful?

Solution

No, you should not do this. It makes no sense.

ECMAScript doesn't have a built-in notion of protocol (as it was originally called in Smalltalk) or interface, and a class with empty methods is not a good approximation of that.

The correct approximation of an interface in ECMAScript is documentation. You should document the protocols your objects need to conform to. After all, it is perfectly possible for an object to conform to the protocol even if it doesn't extend FileManager! That's what OO is all about: as long as an object conforms to a protocol, you can use it, without knowing its implementation (including its class / prototype).

Note: I am not familiar enough with ECMAScript documentation tools and how well they support protocol documentation. (In Ruby, with which I am more familiar, support is practically non-existent, which is a shame.)

A good example of the usage of interfaces in ECMAScript are the iteration interfaces defined in the specification: it first defines what an interface is (bold emphasis mine, italic emphasis from the spec):

An interface is a set of property keys whose associated values match a specific specification. Any object that provides all the properties as described by an interface's specification conforms to that interface. An interface is not represented by a distinct object. There may be many separately implemented objects that conform to any interface. An individual object may conform to multiple interfaces.

And then it describes the different interfaces, e.g. the Iterable interface:

  • Property: @@iterator
  • Value: A function that returns an Iterator object.
  • Requirements: The returned object must conform to the Iterator interface.

There are projects which add type annotations to ECMAScript, e.g. JSDoc supports type annotations for documentation purposes. (Note that there is a difference between type annotations and type checking! Annotations are useful for documentation and communication purposes, i.e. for humans even if not checked by a machine.)

There are also projects which can understand these JSDoc annotations and use them for actual static type checking, e.g. Google Closure Compiler.

Last but not least, there are some languages which are specifically designed to be familiar to ECMAScript developers, which have support for varying degrees of typing. For example, Facebook's Flow is a rather conservative superset of ECMAScript with support for type annotations and type checking, Microsoft's TypeScript is also a superset of ECMAScript that is a tad more ambitious than Flow (i.e. it supports Union and Intersection Types and Generics, and it doesn't just add typing, it also adds other features, for example, it supported classes and generators before ECMAScript did, and it already supports async/await). Basically, the difference between the two is: both are supersets of ECMAScript, but Flow is only a type system, whereas TypeScript adds a type system and additional features.

Moving further away from ECMAScript proper (starting with type annotations in doc comments, external type checkers, and ECMAScript superset languages), there are languages which are not intended to be supersets of ECMAScript and deliberately deviate from it, like Dart (which is still similar to ECMAScript and has optional typing) to languages like PureScript and Elm, which are much more in the strong, strict, statically typed functional language camp and closer to Haskell and ML than ECMAScript, yet still explicitly designed to be usable as ECMAScript replacements in the browser and server-side.

Licensed under: CC-BY-SA with attribution
scroll top