Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static factory method in abstract class

Tags:

oop

typescript

I am building a class system in Typescript. There is a main abstract class Component, that has a static method create(). This method will be called on children to build a particular instance

abstract class Component {
    static build() {
       // some additional logic here, for example, cache to reuse instances
       return new this();
    }
}

class Button extends Component { }
class Input extends Component {}

Button.build(); // returns Button instance
Input.build(); // returns Input instance

Same code in TS Playground

This approach works well in Javascript, but Typescript reports an error at the line new this(), saying "Cannot create an instance of an abstract class."

How can I explain typescript that method will be called on derived instances, but not on the main abstract class directly? Maybe there are other ways to implement the API that I needed?

like image 887
just-boris Avatar asked Mar 29 '18 23:03

just-boris


People also ask

Can we use abstract class in factory design pattern?

Short answer: Yes. Actually, since Java 8 you can provide default implementations for the methods in an interface and the only differences to an abstract class are constructors (which you don't use anyway apparently) and fields which should be private, so there's very little difference.

What is a static method abstract?

A static method belongs to class not to object instance thus it cannot be overridden or implemented in a child class. So there is no use of making a static method as abstract.

Is abstract factory a factory of factories?

Abstract Factory classes are often based on a set of Factory Methods, but you can also use Prototype to compose the methods on these classes. Abstract Factory can serve as an alternative to Facade when you only want to hide the way the subsystem objects are created from the client code.

When would you use static factory method?

A static factory method is a public static method on the object that returns a new instance of the object. These type of methods share the same benefits as the traditional factory method design pattern. This is especially useful for value objects that don't have a separate interface and implementation class.


1 Answers

this is typeof Component, and since Component is abstract class, new this is inadmissible. Even if Component wasn't abstract, Button.build() return type wouldn't be properly handled in child classes.

It requires some type hinting, via generic method:

abstract class Component {
    static build<T = Component>(this: { new(): T }) {
       return new this();
    }
}

class Button extends Component { }

const button = Button.build<Button>(); // button: Button
like image 61
Estus Flask Avatar answered Sep 29 '22 12:09

Estus Flask