3

It might not be possible, but I'm curious. Is it possible to define a private constructor with a public factory method?

function MyParentClass() {}
MyParentClass.prototype.init = function() { ... }

function MyChildClass() {}
MyChildClass.prototype = new MyParentClass();
MyChildClass.prototype.init = function() {
    ...
    MyParentClass.prototype.init.apply(this);
    ...
}
MyChildClass.Create = function() {
    var instance = new MyChildClass();
    instance.init();
    return instance;
}

Is it possible to hide the 2 constructors and only expose Create()?

Other approaches to this overridable init() approach are welcome too. Thank you.

0

1 Answer 1

8

I am not sure what you are trying to achieve, but here's an example where MyClass would be a singleton that has a factory method create that allows creating MyClass instances.

//MyClass will be an object with a create method only
var MyClass = (function() {
    function MyClass() {
        this.initialized = false;
    }

    MyClass.prototype = {
        init: function () {
            this.initialized = true;
            return this;
        }
    };

    return {
        create: function () {
            return new MyClass().init();   
        }
    };

})();

var m = MyClass.create();
console.log(m);
console.log(m.constructor); //Will be Object because we replaced the whole prototype

However, I am not sure why you want to have two constructor functions (init and the constructor itself)? Are you trying to abstract the object creation process away because it is complicated?

I suspect that you simply want to move the constructor logic into another function because of the way you are trying to achieve inheritance.

Are you simply trying to avoid calling the constructor logic when you do the following?

MyChildClass.prototype = new MyParentClass();

If it's the case, using Object.create would fix your problem (it is not supported in old browsers, but there's a shim for it -- the shim support the features you would need, but not everything that Object.create does).

function A(test) {
    this.test = test;
}

function B(test) {
    A.call(this, test); //call parent constructor
}
B.prototype = Object.create(A.prototype); //inherit from A

var b = new B('test');

console.log(b);
console.log(b instanceof A); //true

You could also use a pure prototypal approach, without using constructor functions together with the new keyword.

var A = {
        init: function (test) {
            this.test = test;
            return this;
        }
    },
    B = Object.create(A),
    b;

    //override constructor function
    B.init = function (test) {
        return A.init.call(this, test);
    };

b = Object.create(B).init('test');

console.log(b);
Sign up to request clarification or add additional context in comments.

4 Comments

I think your discussion about inheritance is not what the OP was asking, is it just noise? Maybe I don't get the question either. IMHO, the first section fully answer the question, private constructor, and a factory method that calls it
@JuanMendes, Well I wanted to provide as much details as possible since suspected that the OP was asking this question for bad reasons. Also, it answers "Other approaches to this overridable init() approach are welcome too".
You are correct about the reason for the init function, it's because I needed to avoid the initialization logic in the constructor for the inheritance. But since I can use Object.create to set up the prototype chain instead, I can move the logic back into the constructor. Thank you!
Yes, I should have looked more carefully at what the code was actually doing instead of just the literal question, you actually described inheritance extremely well and concisely. My bad

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.