tag:robotlegs.tenderapp.com,2009-10-18:/discussions/robotlegs-2/3509-instantiate-and-extend-modelsRobotlegs: Discussion 2013-06-25T15:55:23Ztag:robotlegs.tenderapp.com,2009-10-18:Comment/274664702013-06-24T17:01:46Z2013-06-24T17:02:31ZInstantiate and extend models<div><p>hi,</p>
<p>I'm trying to work with a model and extending it.</p>
<p>When say ModelSub extends ModelSuper and I override say function
setSomeVar which<br>
sets a var in ModelSuper, the var in ModelSuper is not being
set.</p>
<p>I think this has to do with how I instantiate the model(s).</p>
<p>Usually, in a non rl project, I would say smt like:<br></p>
<pre>
<code>var model:ModelSuper = new ModelSub();
model.setVar("hey");</code>
</pre>
and the var would be set in ModelSuper.
<p>How do I inject and/or instantiate a sub model in rl to make
this work?</p>
<p>I am now just doing:<br></p>
<pre>
<code>context.injector.map( MyModel ).asSingleton();</code>
</pre>
but I think that is not enough?
<p>thanks,<br>
Jeff.</p></div>JeffW.tag:robotlegs.tenderapp.com,2009-10-18:Comment/274664702013-06-25T08:14:18Z2013-06-25T08:15:48ZInstantiate and extend models<div><p>I guess I need to use interfaces, sth like described here:<br>
<a href=
"http://knowledge.robotlegs.org/discussions/questions/166-map-multiple-interfaces-to-one-singleton-class">
http://knowledge.robotlegs.org/discussions/questions/166-map-multip...</a></p>
<p>But I don't see how exactly. Do both super and sub model need
their own interface?<br>
What do I add in my configure function so that I can inject them in
for instance commands? How do you map a model to its interface in
RL2?</p>
<p>Tried some things like this:<br></p>
<pre>
<code>context.injector.map( ModelSub ).asSingleton();
context.injector.map( ModelSuper ).asSingleton();</code>
</pre>
<pre>
<code>context.injector.map(IModelSub).toSingleton( ModelSub)
context.injector.map(IModelSuper).toSingleton( ModelSuper)</code>
</pre>
but these are just wild guesses that don't work..</div>JeffW.tag:robotlegs.tenderapp.com,2009-10-18:Comment/274664702013-06-25T08:20:28Z2013-06-25T08:20:28ZInstantiate and extend models<div><p>Actually I can set a var in the supermodel from an overridden
function in sub model now, so that is not the problem. The question
is how I can access that var in another command by injecting the
model or its interface...</p></div>JeffW.tag:robotlegs.tenderapp.com,2009-10-18:Comment/274664702013-06-25T08:56:48Z2013-06-25T08:56:48ZInstantiate and extend models<div><p>Hold on, I'll be with you in a bit.</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/274664702013-06-25T09:11:33Z2013-06-25T09:11:33ZInstantiate and extend models<div><p>Using a base class</p>
<p><strong>Mapping</strong></p>
<pre>
<code>injector.map(SomeModel).asSingleton();</code>
</pre>
<p><strong>SomeModel</strong></p>
<pre>
<code>public class SomeModel extends BaseModel
{
public function doSomething():void
{
someProperty = someProperty+" modified in SomeModel";
}
}</code>
</pre>
<p><strong>BaseModel</strong></p>
<pre>
<code>public class BaseModel
{
private var _someProperty:String;
public function BaseModel()
{
}
public function set someProperty(value:String):void
{
_someProperty = value;
}
public function get someProperty():String
{
return _someProperty;
}
}</code>
</pre>
<p><strong>SomeClass</strong></p>
<pre>
<code>[Inject]
public var someModel:SomeModel;
private function someMethod():void
{
someModel.someProperty = "some value";
}
private function anotherMethod():void
{
trace(someModel.someProperty); //traces "some value"
}</code>
</pre>
<p>Somewhere, call someMethod(); then anotherMethod();</p>
<p><strong>AnotherClass</strong></p>
<pre>
<code>[Inject]
public var someModel:SomeModel;
private function execute():void
{
someModel.doSomething();
trace(someModel.someProperty); //traces "some value modified in SomeModel"
}</code>
</pre>
<h1><a name="using-interfaces-" href="#using-interfaces-" class=
"anchor" id="using-interfaces-"></a>Using Interfaces:</h1>
<p><strong>Mapping</strong>:</p>
<pre>
<code>injector.map(ISomeOtherModel).toSingleton(SomeOtherModel);</code>
</pre>
<p><strong>ISomeOtherModel</strong></p>
<pre>
<code>public interface ISomeOtherModel
{
function doSomething():String;
}</code>
</pre>
<p><strong>SomeOtherModel</strong></p>
<pre>
<code>public class SomeOtherModel implements ISomeOtherModel
{
public function SomeOtherModel()
{
}
public function doSomething():String
{
return "done something";
}
}</code>
</pre>
<p><strong>SomeClass</strong></p>
<pre>
<code>[Inject]
public var someOtherModel:ISomeOtherModel;
private function someOtherMethod():void
{
var someString:String = someOtherModel.doSomething();
//someString is "done something"
}</code>
</pre></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/274664702013-06-25T10:09:46Z2013-06-25T10:09:46ZInstantiate and extend models<div><p>If IModel is the interface having a var someProperty:String; and
someMethod();, implemented by ModelA and ModelB, then you’ll
have to map ModelA</p>
<p>injector.map(IModel).toSingleton(ModelA); in Module A</p>
<p>and</p>
<p>injector.map(IModel).toSingleton(ModelB); in Module B</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/274664702013-06-25T10:12:31Z2013-06-25T10:12:31ZInstantiate and extend models<div><p>thanks Ondina, this looks clear to me, and I actually have tried
it this way with various results. I looked at my code again and
what I'm picturing is that I have common code for multiple
contexts. And that I sometimes want to extend this code - a model,
command or view - and sometimes not. If I extend a class I can
inject the extended class as you describe.</p>
<p>Suppose I have a command that I don't want to extend. I just
want to inject the super model into that . This also works - since
1 minute ago - but only if I also map the super model in my config.
It feels funny to map both super and sub model. Is this where some
smart way of working with interfaces comes in? Something like
implementing the interface of a super model onto a sub model.</p></div>JeffW.tag:robotlegs.tenderapp.com,2009-10-18:Comment/274664702013-06-25T10:25:13Z2013-06-25T10:25:13ZInstantiate and extend models<div><p>I’m trying to understand your use case. (reading your
questions from the other post and this one). I’m not quite
sure what you want to achieve.</p>
<p>The common class would be the interface, IModel, that can reside
in a lib, or in the commons folder of the app. In Module A you have
ModelA implementing IModel, and in Module B ModelB implementing
IModel, both sharing someProperty and someMethod(), and each having
(or not) other properties or methods of their own.</p>
<p>The other thing you’re talking about is how to let the
shell know about properties changed in ModuleA or B, and/or how to
pass this properties from a module to another, right?<br>
You’re talking about a SuperModel or something, but you mean
a Shell’s model right?</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/274664702013-06-25T10:29:34Z2013-06-25T10:29:34ZInstantiate and extend models<div><p>Maybe what you want is ModuleA dispatching an event to trigger a
command in the Shell, which would then set properties on a
ModulesModel (your super model?). Then ModuleB, when loaded, would
dispatch an event to trigger another command of the Shell, to get
the properties from ModulesModel?</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/274664702013-06-25T10:37:06Z2013-06-25T10:37:06ZInstantiate and extend models<div><p>Sorry if I'm not clear, which I can imagine.</p>
<p>No, I'm not talking about a shell model, not worried about that
at the moment.<br>
I'm talking about a base model that holds functions and properties
used by both modules. In my eyes an interface would just contain a
list of functions that the module models need to implement whereas
a base model, well, contains the actual shared functions and
properties. I was hoping to somehow access that base model in a
command so that I don't need to write a sub command for every
module with its own model injected.</p></div>JeffW.tag:robotlegs.tenderapp.com,2009-10-18:Comment/274664702013-06-25T13:18:59Z2013-06-25T13:18:59ZInstantiate and extend models<div><p>Sorry for the delay, stuff related to my personal projects has
been keeping me busy.</p>
<p>What you’re saying is that you want to modify properties
in a BaseClass and are expecting that the derived classes would
reflect the changes? That’s not possible.</p>
<p>I might be wrong, but I think that you want something like the
decorator pattern?</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/274664702013-06-25T13:52:06Z2013-06-25T13:52:06ZInstantiate and extend models<div><p>Always glad you answer my posts, no matter if it takes a little
longer:)</p>
<p>I don't think I'm expecting derived classes to reflect changes
in the BaseModel.<br>
Say I have a BaseModel that reside in my common lib. I want to
extend it because there are some differences in how Module A and B
save data into the model. So I create ModelA and ModelB, both
extending BaseModel.</p>
<p>What I'm trying to avoid is to inherit each and every command
that resides in the common lib just to be able to inject ModelA
into MyCommandA and ModelB into MyCommandB, which both extend
MyCommand. Because what if there is no difference between these
'sub' commands? Then I would just like to use MyCommand. But I
cannot inject both ModelA and ModelB into MyCommand. So I was
hoping to somehow inject BaseModel or some interface into MyCommand
and have access to changes made in ModelA or ModelB. Maybe it's
more the other way around: I'm expecting BaseModel to reflect
changes in the derived classes.</p>
<p>Is this possible you think? Because if not, I would need to
extend all the base commands, even if they are similar for A and B,
just to inject ModelA and ModelB.</p></div>JeffW.tag:robotlegs.tenderapp.com,2009-10-18:Comment/274664702013-06-25T15:03:08Z2013-06-25T15:08:10ZInstantiate and extend models<div><p>Hehe, Jeff. The other way around wouldn’t work either.</p>
<p>One thing to notice is that ModelA and ModelB could implement
different interfaces, even if they extend a BaseModel. Also, as
you’ve noticed, ModelA and ModelB can have their own methods
in addition to the ones inherited from a BaseModel.</p>
<p>Or, ModelA and ModelB implement the same interface, and
you’d inject the interface into the classes that need
them.<br>
In ModuleA, you mapped it like this:
injector.map(IModel).toSingleton(ModelA); and you inject it like
this:<br>
[Inject] public var model:IModel; //an instance of ModelA will be
used</p>
<p>So a command wouldn’t have to know anything about the
concrete classes, if you injected the interface.</p>
<p>Also, a class can implement more than one interface, as you
probably know.</p>
<p>Another thing is that of what a sub-context inherits from its
parent.<br>
Say, you have a mapping in the parent:</p>
<p>injector.map(SomeCrazyClass).asSingleton();</p>
<p>If you use the ModularityExtension without modifying its default
settings (ModularityExtension(inherit:Boolean = true,
expose:Boolean = true)), then<br>
a sub-context will inherit the mapping of SomeCrazyClass, and you
could inject it into your sub-context’s classes.</p>
<p>If you don’t want a sub-context to inherit from its
parent, you configure it like this:<br>
.install(MVCSBundle, new ModularityExtension(false))</p>
<p>In this case you have to map SomeCrazyClass in the
sub-context.</p>
<p>Also, even if you mapped it in the parent context, and you used
the default inherit:Boolean = true, if you map it in the
sub-context, the subcontext will use its own mappings.</p>
<p>I just wanted to mention all this, just in case you didn’t
know how subcontexts inherit from parent. So, sorry in case you
knew.</p>
<p>Now, after that much back and forth I don’t know anymore
what to say and I feel like I’m missing your point entirely.
I’m getting dizzy ;)<br>
I think it would be easier to attach an example of what
you’re trying to achieve, and I could tell you which solution
I’d choose after looking at your classes.</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/274664702013-06-25T15:26:27Z2013-06-25T15:26:27ZInstantiate and extend models<div><p>Ondina, I got it working now, thanks to your explanation. Sorry
you feel dizzy :)</p>
<p>So for now I simply extend ModelA and ModelB with a BaseModel
and they both implement the same interface, which I inject in
commands that don't have to know about the concrete classes. That
interface was what I was looking for!</p>
<p>Actually I wasn't aware of how sub-contexting and inheritance
works, will look into that later and maybe move some mappings to
the shell. Have a good evening!</p></div>JeffW.tag:robotlegs.tenderapp.com,2009-10-18:Comment/274664702013-06-25T15:31:52Z2013-06-25T15:31:52ZInstantiate and extend models<div><p>Ah, cool! A nice evening to you, too.:)</p></div>Ondina D.F.