Switching multiple interfaces of an object

I’ve been toying with some code that does what I believe people asking
for #unextend normally need.

It allows one object to have several different interfaces (possibly
overlapping, ie. with the same method names) and to let the client
select which one to use as in

A = a.new
a.foo
a.bar 1,2,3
a.with_interface(:extended) do
a.foo(‘arguments’,‘possibly’,‘required’,‘with’,‘this’,‘interface’)
a.bar 1,2,3
end

the class definition would be something like

class A
include InterfaceSwitching

    def initialize
            set_interface :normal
    end

    def foo
            puts "A#foo"
    end

    def bar(*args)
            puts "A#bar: #{args.inspect}"
    end

    def_interface :normal, :foo, :bar

    def foo(*args)
            puts "A(extended)#foo, ignoring args"
    end

    def bar(*args)
            r = args.map { |i| i * 2 }
            puts "A(extended)#bar: #{args.inspect} => #{r.inspect}"
    end

    def_interface :extended, :foo, :bar

end

of course, it could be used this way too:
class A
include InterfaceSwitching

include SomeModule1
def_interface :somemodule1, *SomeModule1.instance_methods

include SomeModule2
def_interface :somemodule2, *SomeModule2.instance_methods

end

Is this useful at all?
I thought of this as I was writing on the Adaptor pattern. I consider
the above to be a “generalized” (dynamic) adaptor.

···


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

How should I know if it works? That’s what beta testers are for. I
only coded it.
– Attributed to Linus Torvalds, somewhere in a posting

Is this useful at all?

very.

I thought of this as I was writing on the Adaptor pattern. I consider
the above to be a “generalized” (dynamic) adaptor.

looks very cool. i’ve done something similar (i think) using delegation:

~/eg/ruby > cat interface.rb
#!/usr/bin/env ruby
require ‘delegate’

class Klass < SimpleDelegator

def initialize
@data = Data.new
@a, @b, @c = [InterfaceA, InterfaceB, InterfaceC].map{|i| i.new @data}
super @a
end

def interface= interface
setobj(
case interface.to_s
when %r/^InterfaceA$/i
@a
when %r/^InterfaceB$/i
@b
when %r/^InterfaceC$/i
@c
else
raise
end
)
end

private
class Data
attr :data
def initialize; @data = 42; end
end
class InterfaceA
def initialize data; @data = data; end
def meth; “InterfaceA: #{@data.data}”; end
end
class InterfaceB
def initialize data; @data = data; end
def meth; “InterfaceB: #{@data.data}”; end
end
class InterfaceC
def initialize data; @data = data; end
def meth; “InterfaceC: #{@data.data}”; end
end
end

k = Klass.new
p k.meth

%w[InterfaceC InterfaceB InterfaceA].map{|i| k.interface = i and p k.meth}

~/eg/ruby > ruby interface.rb
“InterfaceA: 42”
“InterfaceC: 42”
“InterfaceB: 42”
“InterfaceA: 42”

care to comment on the relative merits/drawbacks of these approaches? i really
do think something standard like this would be extremely useful.

-a

···

On Wed, 18 Jun 2003, Mauricio [iso-8859-1] Fernández wrote:

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ara.t.howard@noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
~ > ruby -e ‘p(%.\x2d\x29…intern)’
====================================

Is this useful at all?

very.

I thought of this as I was writing on the Adaptor pattern. I consider
the above to be a “generalized” (dynamic) adaptor.

looks very cool. i’ve done something similar (i think) using delegation:

[some 51 lines of code]

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 :slight_smile:

My code basically involves aliasing methods as needed to get the right
ones to have the required name.

Cons: (w.r.t. delegation)

  • 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 :slight_smile:

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.
  • 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
  • it can be made to work with singleton methods, so they get
    registered as part of the interface.
  • 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).

You can find the code at

If there’s interest in a such a thing I have a couple ideas which should
work much better.

···

On Thu, Jun 19, 2003 at 12:35:12AM +0900, ahoward wrote:

On Wed, 18 Jun 2003, Mauricio [iso-8859-1] Fernández wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

“You, sir, are nothing but a pathetically lame salesdroid!
I fart in your general direction!”
– Randseed on #Linux

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 :slight_smile:

lol. that’s a first for me on c.l.r.! well - ts hasn’t responded so
perhaps i’ve spoken too soon…

My code basically involves aliasing methods as needed to get the right
ones to have the required name.

Cons: (w.r.t. delegation)
^^^^^
^^^^^
^^^^^ ??

  • 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 :slight_smile:

how about marshaling? if you dynamically alias methods - can you marshal
that?

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
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?

  • 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
that oo programming talks about putting data and methods together and here we
go separating them… :wink: 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…

  • 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…

  • 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

class Klass
def Klass.register_interface interface
unless @trust
raise unless has_right_methods interface
raise unless passes_unit_test interface
raise unless some_constraint_or_another interface
raise unless etc interface
end
end
end

Klass.register_interface MyInterface

You can find the code at
http://www.rubygarden.org/ruby?AdaptorPattern/Generalized

i’ll check it out.

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…

-a

···

On Thu, 19 Jun 2003, Mauricio [iso-8859-1] Fernández wrote:

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ara.t.howard@noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
~ > ruby -e ‘p(%.\x2d\x29…intern)’
====================================

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 :slight_smile:

lol. that’s a first for me on c.l.r.! well - ts hasn’t responded so
perhaps i’ve spoken too soon…

:smiley:

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 :slight_smile:
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 :slight_smile:

how about marshaling? if you dynamically alias methods - can you marshal
that?

The class or the object :slight_smile: ?

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 :slight_smile: 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 :slight_smile:

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 :slight_smile:

and delegation with “evil restrictions” :wink: ??

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 :slight_smile:

that oo programming talks about putting data and methods together and here we
go separating them… :wink: 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 :slight_smile:

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.

···

On Thu, Jun 19, 2003 at 04:16:12AM +0900, ahoward wrote:

On Thu, 19 Jun 2003, Mauricio [iso-8859-1] Fernández wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
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