www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - automatic type creation

reply "Frustrated" <c1514843 drdrb.com> writes:
I'd like to support extensions of my own interfaced based design
where anyone could simply "drop" in there own inherited classes
and everything would work as if they designed everything using
those classes from the get go.

To do this though, I need a way to know how to generate these
unknown types(except I know the inherit the interface I have
designed).

e.g.,

interface A
{
     static final A New()
     {
         return new myA;  // we have to return something tangible
that acts like A.
     }
     ....
}

class myA : A    //never used directly except as a "base" for
actual work, A is used as the reference type in all programming
and myA is "hidden".
{
     ....
}

class anotherA  : A // someone elses A, not known at all at
compile time. This may be generated by a dll at some future point
{
     ....
}

...

In the production code, myA, anotherA, and any other class based
on A will never be used, only the interface A.

e.g.,

auto a = A.New();

which obviously returns a myA. I do not want this if the anotherA
is now meant to be used, that is, the user of the code wants to
redefine the behavior of all the code I write by plugging in
their own class implementation instead of using mine.

This is all fine and dandy and easy to accomplish by adding a
static delegate A which can then be overridden to return anotherA
after the fact.


The method I'm actually using is to use a template that
essentially returns the concrete implementation of any interface
I have designed. This then produces identical results as if I
just used classes directly but by using interfaces too I can have
multiple inheritance. But as far as coding is concerned I just
use the interfaces but any time I "new" an interface it's
corresponding class is returned.

Of course, the problem with this is that it's an either or
approach. Either my implementation is completely used or not.

What I'd really like is a way to create objects for the
interfaces that at any point could be any one of the
implementations of the interface.

This way, essentially, the following could be done:

auto a = A.New(); // returns myA

//somewhere else were an anotherA is meant to be used:

auto b = A.New(); // returns anotherA

which, of course, as is, won't work unless New somehow knew when
it was suppose to use myA's and use anotherA's(Which would be
cool if it could because then the user could replace my
implementations selectively where ever it wants).

The only thing I can think of that might work is to supply a
parameter to New that tells it which object to return and allow
the user to add their own creation mechanism to the delegate(sort
of like allowing them to add to a switch statement dynamically).

I'd then have to save/restore dynamically the parameter at every
New() call so it is never hard coded(which would allow it to be
changed how ever and the change would persist in the program).


I will give you an example:

Suppose you have an Icon interface that draws icons and allows
interaction and all that. You also implement a "default" type of
icon that simply displays the icon image.

Now suppose you want to allow others to write their own
implementations. Say someone want's to add right mouse button
properties to it, the ability to "execute" the icon, etc.

As far as you are concerned within the own logic of your program,
it matters not what they do. You want icons to be used in a
specific way, say to be visualized on a desktop. If people want
to expand on your idea still within some constraint of the
interface, you have no problem with that.

While you can predict all possible uses and you can write code in
a way that might satisfy everyone's implementation ideas, you can
at least, allow them to implement the interface on their own and
possibly provide them with some generic stuff that "most" people
would need. The main thing is, you have the interface to work
with and they supply that at a minimum so their implement will
"plug and play".

BUT!!! What if 10 people implement 10 completely and all cool
icon classes and you want some way to allow all 10 to be used in
any way desired. If the user wants 1 of each they can have it.

In this case you can't use the all or nothing approach. Each
implementation still is "plug and play" but how to allow any to
be used when it is suppose to?

This necessitates that New is more complex. A sort of factory
that has some idea on it's own which type of object it is suppose
to return *when*.

It would be very similar to the Dependency Injection pattern but
because it occurs at creation this is impossible(and static
injection of the creation mechanism doesn't seem very safe nor
"generic").

So, in my own code I would have many lines of code that use
something like "new myIcon;", which forces me to use my own
implementation. If I changed it to a sort of static factory I
might have "Icon.New()" which returns whatever specific
implementation but for all further created icons until it is
changed again. (that is, Icon.New() is a sort of static
dependency injection where someone somehow could insert the
proper creation code for which Icon they want created)

None of these solve the problem though and they require me coding
in such a way as to take into account that every time I create a
new icon I have to know exactly which one to create and then use
an appropriate method to create it. e.g., a Factory pattern.

But maybe there is a better way? What if Icon.New() somehow knew
which icon it was suppose to return? If this was the case there
would be no difference in coding for one class as for many and
writing "plug and play" code would be extremely simple.

In this case Icon.New would need to know the state of the system
and all information to make the correct decision. Maybe this is
not possible? In general, I would think most simple cases could
be handled. My particular use is very similar to the icon example:

1. Initially all icons are the "default" icons.
2. When an icon is changed from the default icon to a different
type it is always "externally" initiated. That is, either the
user of the icons or a program or whatever decides to use a
different type of icon.

This is a key piece of information because it is when the "state"
has "changed".

When we are creating the icons on the desktop the next time
around(after a reboot), this state information must be used to
determine which implementation to load.

3. Some way for the external to change implementation must be
implemented in the design, else there would never be any way to
get them off of default.

Which should be all that is required. Step 2 is the hard part. If
it could be automated(somehow every time New is used it is able
to gather all the information it needs to determine which
implementation to create, and ever time an implementation
changes(from step 3), then everything should work and be very
simple to use), then it would be quite a simplification(and
probably pretty generic).

So, is there any pattern like this? (BTW, I am not talking about
a factory pattern, unless you want it to be called the
intelligent automatic abstract factory pattern)



If you still don't understand what I'm trying to achieve, try to
come up with a design for the icon interface, e.g.:

interface Icon
{
      void DisplayImage();
}

class defaultIcon : Icon
{
     int x, y;
     Image image;
     void DisplayImage() { DrawImage(x,y, image); }
}

....

     // Desktop drawing routing
     foreach(icon; Icons)
     {
          icon.DisplayImage();
     }


in the above code, the interface supplies exactly what you want
an icon to do(possibly minimally). You can display icons with
this. Nothing more, nothing less.

Now suppose someone wants to come along and add mouse support,
execution, etc. They can still do this and it is still "plug and
play" but it would require more work on their part because they
would have to hook into many different subsystems(keyboard,
mouse, etc). You could make your interface more complex to
provide these features directly if it was needed., e.g.,


interface Icon
{
      void DisplayImage();
      event MouseAction(...);
}


or whatever.

In any case, suppose we now have

class superDuperIcon : Icon
{
     // this is a really cool class that makes those boring default
icons awesome!
}


Now why should this class be any more difficult to use *just*
because it is created *after the fact* of the original design.
Obviously if we knew all the types of icons that anyone might
create we could more easily create them.... but we do, in a
sense!!

e.g., suppose I initially created an OS using the icon code and
had the defaultIcon to use because I was to lazy to create
anything else and just wanted things for test.

Suppose I compile the code for the OS and it takes 13.9269 years,
but it is freaken Amazing... everything but that stupid default
icon!

I could refactor the code, implement superDuperIcon and replace
all uses of defaultIcon with superduperIcon. This is pretty easy
to do... but will again take 14.2123 years to recompile(a little
longer cause the hard drive got a bit more fragmented).

But has anything really changed in the code? Of course not!
superDuperIcon is still being used as the Icon
interface(remember, we are programming to interfaces).

So why should we have to recompile the original code have to know
anything about any implementations of Icon EVER? It doesn't
except to know that their might be some(else we would just use a
final class instead). And why should be any more complicated to
"plug in play" superDuperIcon? Of course some extra code will
have to be written but it should be simple, straightforward, and
safe. Of course if we make new dynamic then we essentially are
using the dynamic dependency injection which is relatively simple
in this case.

NOW WHAT?!?!

It's obvious!! We end up writing another implementation:

class reallyFastPostModernUltimateIcon : Icon { ... }

Now, this implementation is actually better than
superDuperIcon... and we really want to simply drop that in and
make everyone use it. But some people just can't deal with
change... they still want to use the old defaultIcon... and
others still want to use the superDuperIcon.

Now what? Do we allow only one to be used at any give time. You
can have all default, all superDuper, or all reallyFast icons,
but not mixed in any way? Maybe! Maybe not!

If we want people to use our reallyFastPostModernUltimateIcon we
need to make it available to even those that are not using it so
maybe if they accidentally change one of the icons(only one so it
won't be too much of a shock or they don't notice it) they will
realize how awesome it is and how amazing we are for creating it.

But how can we make our code we are writing allow all these
implementations to be plugged in and mixed and all that without
having to write complicated stuff? After all, if each class can
very easily be used as a all or nothing approach why is the mixed
approach so much more complex(several orders of magnitude just
based on lines of code)?

I propose it isn't. I propose there is a very simple pattern(at
least in most cases) that is nearly as simple as if one could
assume only one icon type could ever exist. I have no proof that
such a design is possible................

I don't even have any hearsay.

Actually, All I have is this forum, some spare time(sick,
couldn't sleep... so blame all the bad grammar and spelling
mistakes on Mr. Allergy), and the ability to make letters and
words magically appear in your mind as you read this!

Anyways have fun... if you have anything useful to say, feel
free. If you felt this was a waste of your life then why did you
read it in the first place? Not like I held a gun to your head!!!
Jan 25 2014
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
Where is the tldr; section? :)

On 01/25/2014 04:08 AM, Frustrated wrote:

 I'd like to support extensions of my own interfaced based design
 where anyone could simply "drop" in there own inherited classes
 and everything would work as if they designed everything using
 those classes from the get go.
I think the concept-based polymorphism popularized by Sean Parent may be relevant. The following is an example where the "subtypes" Cat and Dog are not inherited from Animal but still behave specially. The design naturally allows hierarchical designs where for example an Animal of Animal(Dog) can be constructed. (See the WAT? line below.) import std.stdio; struct Animal { void sing() { animal.sing(); } this(AnimalT)(AnimalT animal) { this.animal = new Model!AnimalT(animal); } private: interface Interface { void sing(); } class Model(T) : Interface { T t; this(T t) { this.t = t; } void sing() { t.sing(); } } Interface animal; } struct Cat { void sing() { writeln("meow"); } } struct Dog { void sing() { writeln("woof"); } } void main() { Animal[] animals = [ Animal(Cat()), Animal(Dog()), Animal(Animal(Dog())) /* WAT? :) */ ]; foreach (animal; animals) { animal.sing(); } } Ali
Jan 25 2014
parent reply "Frustrated" <c1514843 drdrb.com> writes:
On Sunday, 26 January 2014 at 05:19:51 UTC, Ali Çehreli wrote:
 Where is the tldr; section? :)

 On 01/25/2014 04:08 AM, Frustrated wrote:

 I'd like to support extensions of my own interfaced based
design
 where anyone could simply "drop" in there own inherited
classes
 and everything would work as if they designed everything using
 those classes from the get go.
I think the concept-based polymorphism popularized by Sean Parent may be relevant. The following is an example where the "subtypes" Cat and Dog are not inherited from Animal but still behave specially. The design naturally allows hierarchical designs where for example an Animal of Animal(Dog) can be constructed. (See the WAT? line below.) import std.stdio; struct Animal { void sing() { animal.sing(); } this(AnimalT)(AnimalT animal) { this.animal = new Model!AnimalT(animal); } private: interface Interface { void sing(); } class Model(T) : Interface { T t; this(T t) { this.t = t; } void sing() { t.sing(); } } Interface animal; } struct Cat { void sing() { writeln("meow"); } } struct Dog { void sing() { writeln("woof"); } } void main() { Animal[] animals = [ Animal(Cat()), Animal(Dog()), Animal(Animal(Dog())) /* WAT? :) */ ]; foreach (animal; animals) { animal.sing(); } } Ali
While this is interesting I don't think it specifically addresses the issue of having only to create the "interface" in the original code but have it automatically create the desired type at runtime. In the above code you have to specify cat and dog and are simply wrapping the desired code. If I were using the above code it would be something like Animal[] animals = [Animal.New(State), Animal.New(State), Animal.New(State)]; and somehow New would use the state to know which to create(in this case, cat, dog, and an animal wrapped dog). (of course, the above code would be rather useless and hard to determine the appropriate state information)
Jan 25 2014
parent "Frustrated" <c1514843 drdrb.com> writes:
Here is something I just did that essentially demonstrates what I
am talking about(bugs withstanding):

http://dpaste.dzfl.pl/d82b6274

It is not exactly how I should be going about it as it is
somewhat generic but not properly designed to allow the concrete
implementations needed

void main()
{
	void *data = null;
	auto a = A.New();
	auto b = A.New(otherA.StaticFactoryObjectData.Default);
	a.foo();
	b.foo();
}


Notice that myA and otherA are never referenced in the code
except possibly in the argument to New, which would generally be
loaded up from a file so it is irrelevant here.

So, the point is, basically, one could create a new subtype of A
and plug it in at runtime with the following two cases:

1. I never how to worry about what the new subtype might do or
even think about it much beyond using the static factory stuff,
which for the most part is taken care of in the
templates(slightly more work but not much)).

2. I do not have to change the code in any way from what it would
be without using the pattern(no plug and play) except that New
must keep tract of state data, which isn't much work beyond
saving and restoring the data to a file.

I simply use A, the interface, as the type and do what I want to
do with it and completely neglect any implementation of it(of
course I have to design a default myself but in some sense that
is irrelevant to the design since it is implementation based).


Using New() is bad because it prevents plug and play(the default
will always be used). But using New(objectData) is generic,
allows one to plug in any subtype of A as long as objectData is
not hard coded(basically it needs to be backed by a file and a
way for the user to modify the file(indirectly through a gui).

So the code essentially does this but isn't that useful as it
stands(using the templates makes it slightly difficult to extend
A properly... it can be done but I want even more generic way to
do this(right now initializing the object's with the data is the
issue. Serializing the subtype would probably make it generic
enough and wouldn't require much work from the user beyond using
the templates and the slight change in coding make New generic).


Anyways, maybe someone has some useful comments about this
approach(ways to make it better or pitfalls, etc...).
Jan 27 2014