From: "Mauricio Fernández" Date: 2003-06-19T05:11:01+09:00 Subject: Re: switching multiple interfaces of an object On Thu, Jun 19, 2003 at 04:16:12AM +0900, ahoward wrote: > On Thu, 19 Jun 2003, Mauricio [iso-8859-1] Fern�ndez wrote: > > > > care to comment on the relative merits/drawbacks of these approaches? i really > > > do think something standard like this would be extremely useful. > > > > Ummm, your code is *way cleaner and simpler* :-) > > lol. that's a *first* for me on c.l.r.! well - ts hasn't responded so > perhaps i've spoken too soon... :-D Now, it's really no wonder: as I love toying with singleton classes, class instance variables and such, I think I abuse them a little bit :) So I tend to write baroque code when I do it for fun only, as in this case at first. > > > My code basically involves aliasing methods as needed to get the right > > ones to have the required name. > > > > Cons: (w.r.t. delegation) > ^^^^^ > ^^^^^ > ^^^^^ ?? with regard to (I thought this was a common abbreviation in English, but I'm no native speaker...) > > * threading issues: the current interface used for one object must be > > the same in all threads (or non-interfering interfaces) > > * more complicated > > * uses 1 class instance variable (bad in the sense that if you mess > > with that it breaks :) > > how about marshaling? if you dynamically alias methods - can you marshal > that? The class or the object :-) ? Objects should be easily 'marshallable', the only thing that needs to be saved is the currently supported interface. Perhaps something like obj = Marshal.load(io) obj.setInterface(:foo) would be necessary. > > Pros: (ditto) > > * in your code you have to create internal classes, whereas I am only > > adding methods and saying "methods foo, bar and baz as defined right > > now correspond to interface Babar". So I think although the > > implementation I did is more complicated, its use is actually easier. > > but perhaps less safe. the reason i have all the classes and interface defs > as private is that, only the class designer should, really, know which well, if you're messing with class SomeClass # stuff end (which is what you have to do to add new interfaces with my code) you definitely have to know how the class works, so I don't see why delegation would be safer on this very issue. However, I have the feeling that method aliasing is easier to break if you mess with its internals (class instance variables, etc) > different interfaces are possible and what constraints there are (eg. once > you use interface 'x' the object may not ever be used via interface 'y' - > these situation are not that hard to imagine...) maybe this is just the evil > c++ side of me coming out? It's a little evil IMHO, yes :) If only the first interface that was used is kept, and the client has to specify it, then you might as well directly write 4 different classes that implement something in terms of another and then let the client explicitly initialize whichever we wants. (I know its only one case but I just couldn't help writing this :) I mean, what's the difference between class Implementation #... end class SupportsInternface1 # do things with implementation, perhaps using delegation or actually # subclassing Implementation and aliasing methods as needed, etc end class Bla2 #ditto end # now the users chooses the "interface" obj = Bla2.new #from now on can only use the interface offered by Bla2 :-) and delegation with "evil restrictions" ;) ?? Now seriously, IMHO interfaces should always be available because otherwise this is not an Adaptor but a State pattern... > > * this means your classes don't normally share state unless you do > > explicitly pass it around (which you do in your code), so it seems > > more difficult to do this "extend and define interface" thing and > > don't have direct access to instance vars > > i see that. however, my idea was simply to separate data from methods, and to > let the methods be 'assign-able'. eg. to switch interfaces. kind of funny One of my goals was allowing methods to be defined just the same way as if you were implementing all these interfaces in separate classes. This requires direct access to instance variables. In other words, I only wanted to fix one problem, name clashes in interfaces, without creating any other :) > that oo programming talks about putting data and methods together and here we > go separating them... ;-) i guess i'm thinking that, although it is certainly > possible to separate methods from data (as i did) there is still a potentailly > *very* tight coupling between the two - thus the private inner class thing... As there's so much coupling I believe it's better to offer direct access to i.v. with @attr instead of accessors or anything else. After all this is supposed to be one object offering different interfaces, not several objects using services from a third. > > * it can be made to work with singleton methods, so they get > > registered as part of the interface. > > in my code, all that would be needed to do this is an > > attr :interface > > in other words, you can do this if the interface class is publicly available: > > class << k.interface > def foo; 'foo'; end > end > > you get the idea... ummm, you add the method to the singleton of the class, but is it going to work at all? I believe it should be k.interface.class_eval <<-EOF def foo; 'foo' end EOF > > * therefore w/ your code interfaces and their implementations have to > > be known beforehand, whereas with mine it's easier to add them on the > > fly (Object#extend). > > i wouldn't agree here, although it would make the code longer than 51 lines > one could easily design I guess it can be done, but then you'd lose one of the pros (clean and short code :) > > You can find the code at > > http://www.rubygarden.org/ruby?AdaptorPattern/Generalized > > i'll check it out. it's quite a kludge now that I see it again, really. > > If there's interest in a such a thing I have a couple ideas which should > > work much better. > > i, for one, like the idea alot. yours may be alot better - i'm just > brainstorming... My code still has this hackish smell, but I have one idea that could be much better. -- _ _ | |__ __ _| |_ ___ _ __ ___ __ _ _ __ | '_ \ / _` | __/ __| '_ ` _ \ / _` | '_ \ | |_) | (_| | |_\__ \ | | | | | (_| | | | | |_.__/ \__,_|\__|___/_| |_| |_|\__,_|_| |_| Running Debian GNU/Linux Sid (unstable) batsman dot geo at yahoo dot com /* * Please skip to the bottom of this file if you ate lunch recently * -- Alan */ -- from Linux kernel pre-2.1.91-1