Injections, Subclassing, and Singletons

yishayjobs's Avatar

yishayjobs

15 Apr, 2015 12:05 PM

Hi,

In have 2 model classes: Model and ExtendedModel. Some commands require Model and other, more specialized ones, require ExtendedModel. I'd like Model to be a singleton and that the same instance be used by all commands, whether they expect Model or ExtendedModel. So this is how I configured it:

            injector.map(ExtendedModel).asSingleton();
            injector.map(Model).toSingleton(ExtendedModel);

The problem is that 2 different instances are injected.

in command A:

[Inject]
public var model:Model;

In command B:

[Inject]
public var extendedModel:ExtendedModel;

How can I change the configuration so that model == extendedModel ?

Thanks.

  1. Support Staff 1 Posted by Ondina D.F. on 16 Apr, 2015 12:57 PM

    Ondina D.F.'s Avatar

    Hi,

    In have 2 model classes: Model and ExtendedModel.

    That means that Model is the superclass and ExtendedModel the subclass, right?
    So, ExtendedModel extends Model?

    I'd like Model to be a singleton and that the same instance be used by all commands, whether they expect Model or ExtendedModel.

    Why would you want that? If a class needs ExtendedModel, why would you give it a superclass?

    How can I change the configuration so that model == extendedModel ?

    Does this mean that you want the superclass to behave like the subclass? If so, then what's the purpose of subclassing? A subclass should inherit all the methods of a superclass, override superclass' methods if need be, and perhaps have some additional methods of its own.

    I guess, that your intention is to inject the Superclass somewhere, change its properties, and then when you inject the Subclass somewhere else, you're expecting that the Subclass' properties reflect the changes in the Superclass. But, that's not possible. Changes made in superclasses are not reflected in the subclasses, or vice versa.

    Forget about injection and mappings for a moment, and just try out a simple example:
    Create a SomeSuperClass with getters and setters for someProperty. Set it to a default value of, say, "Super".
    Create another class, SomeSubClass, that extends SomeSuperClass.

    Then somewhere in your code instantiate the claasses:
    var someSuper:SomeSuperClass = new SomeSuperClass();
    var someSub:SomeSubClass = new SomeSubClass();

    Set someSuper.someProperty to a new value, and trace out the results for someSuper.someProperty and someSub.someProperty. You'll see that someSub.someProperty will not change.

    This mapping
    injector.map(Model).toSingleton(ExtendedModel); doesn't make sense for your use case.

    I guess you've seen this kind of mapping used for interfaces:
    injector.map(ISomeModel).toSingleton(SomeModel);

    But a superclass doesn't behave like an interface.

    Some commands require Model and other, more specialized ones, require ExtendedModel.

    Then you need 2 mappings:

    injector.map(Model).asSingleton();

    injector.map(ExtendedModel).asSingleton();

    In case I misunderstood your question or your use case, please try to explain in more detail what you need to happen with your Model and ExtendedModel when you inject them into other classes.

    Ondina

  2. 2 Posted by yishayjobs on 16 Apr, 2015 01:52 PM

    yishayjobs's Avatar

    Hi Ondina,

    Thanks so much for responding.

    Yes, ExtendedModel extends Model. My application's behavior is configurable. Depending on the configuration some events, and thus some commands, will fire and some will not. Some commands will be executed regardless of the configuration. I'd like the singleton model to reflect the different configurations.

    Consider the following setup:

    Model, ConfigAExtendedModel, ConfigBExtendedModel, CongfigACommand, ConfigBCommand, AnyConfigCommand.

    In configuration A:

    ConfigACommand -> ConfigAExtendedModel
    AnyConfigCommand -> Model

    in configuration B:

    ConfigBCommand -> ConfigBExtendedModel
    AnyConfigCommand -> Model

    AnyConfigCommand can be used in both configurations because it relies only on the model's basic API which is represented in Model.

    I've worked around the problem by doing

                var extendedModel:ExtendedModel = new ExtendedModel();
                injector.map(ExtendedModel).toValue(extendedModel);
                injector.map(Model).toValue(extendedMode);

    but that I don't get lazy instantiation.

    I hope that makes my problem more clear.

    Thanks.

  3. Support Staff 3 Posted by Ondina D.F. on 16 Apr, 2015 03:35 PM

    Ondina D.F.'s Avatar

    No problem.

    Thanks for providing more details.
    Interesting workaround. If it works for you, all is good:) I can't think of anything better than your solution, right now.

    Just in case you want a class to have its dependencies satisfied by the injector, you should let the injector instantiate it. So, instead of new ExtendedModel() do this:

    var extendedModel: ExtendedModel = injector.getOrCreateNewInstance(ExtendedModel);

  4. 4 Posted by yishayjobs on 19 Apr, 2015 07:22 AM

    yishayjobs's Avatar

    Sounds good.

  5. Ondina D.F. closed this discussion on 24 Jun, 2015 01:35 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac