Abstract class or interface?

Hi all again :),

How could I implement this model?

Window <>--------------------- Button
                                  ^

···

                                  >
                          -----------------
                          > >
                       BigButton LittleButton

Being 'Button' an abstract class or an interface.
I mean, how do I define an interface? Must I use modules?

EdUarDo said:

Hi all again :),

How could I implement this model?

Window <>--------------------- Button
                                  ^
                                  >
                                  >
                          -----------------
                          > >
                       BigButton LittleButton

Being 'Button' an abstract class or an interface.
I mean, how do I define an interface? Must I use modules?

If Button is a like a Java interface (i.e. no behavior), then you don't
need one in Ruby. Just implement BigButton and LittleButton with
compatible methods.

If there is shared code in Button, then you can (1) create a class Button
and inherit from it in BigButton and LittleButton, or (2) Create a Button
module and include it in both Big and Little Buttons.

···

--
-- Jim Weirich jim@weirichhouse.org http://onestepback.org
-----------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)

EdUarDo <eduardo.yanezNOSPAM@NOSPAMgmail.com> writes:

Hi all again :),

How could I implement this model?

Window <>--------------------- Button
                                  ^
                                  >
                                  >
                          -----------------
                          > >
                       BigButton LittleButton

Being 'Button' an abstract class or an interface.
I mean, how do I define an interface? Must I use modules?

In Ruby, modules are like abstract classes except you can
inherit from any number of them; or like interfaces except
you can put method bodies in them.

Anyway, because Ruby is not statically typed, you never have
to define an interface before using it. As long as you
don't call a method ‘foo’ on an object that does not
understand ‘foo’, Ruby doesn't care.

This is what people mean when they talk about “duck typing”:
there are no interfaces except the *actual* interfaces.

If the two kinds of buttons have some common functionality,
put that into Button; if they don't, you don't even have to
define the Button class, because it would serve no purpose.

   class BigButton
     def push ; puts "Hey, don't push me!" end
   end

   class LittleButton
     def push ; puts "*whimper*" end
   end

   def abuse_button(button)
     5.times { button.push }
   end

···

--
Daniel Brockman <daniel@brockman.se>

    So really, we all have to ask ourselves:
    Am I waiting for RMS to do this? --TTN.

In Ruby, we take a relaxed approach to interface. Quite literally, an interface is simply a provided set of methods to call, right?

Our philosophy, Duck Typing, is: If it walks like a duck and talks like a duck, it's a duck. In other words, if it supports the methods we want to call, that's all we care about.

This probably sounds a little unstructured. I know it scared the Java side of me when I came over. Don't be surprised it you find yourself liking it when it finally "clicks" though. It frees you do surprising things:

irb(main):001:0> # The following method needs an object supporting <<...
irb(main):002:0* def append_one_to_ten( target )
irb(main):003:1> (1..10).each { |n| target << n }
irb(main):004:1> end
=> nil
irb(main):008:0> arr = Array.new
=>
irb(main):009:0> append_one_to_ten arr
=> 1..10
irb(main):010:0> arr
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb(main):011:0> class Sumation
irb(main):012:1> def initialize
irb(main):013:2> @total = 0
irb(main):014:2> end
irb(main):015:1> def <<( amount )
irb(main):016:2> @total += amount
irb(main):017:2> end
irb(main):018:1> attr_reader :total
irb(main):019:1> end
=> nil
irb(main):020:0> sum = Sumation.new
=> #<Sumation:0x30bab8 @total=0>
irb(main):021:0> append_one_to_ten sum
=> 1..10
irb(main):022:0> sum.total
=> 55

How did I define the interface? The comment above the method. No, I'm not kidding.

Don't check type, generally you shouldn't even check for the method. Just call it. The caller was warned what to pass and if they ignore that an Exception will be thrown, as it should.

Obviously, there are great uses for classes and modules when you do need to share some implementation. However, in Ruby loosen your strangle hold on interface. You'll be surprised what it can do for you.

"Free your mind." :wink:

James Edward Gray II

···

On Jul 22, 2005, at 10:50 AM, EdUarDo wrote:

Hi all again :),

How could I implement this model?

Window <>--------------------- Button
                                 ^
                                 >
                         -----------------
                         > >
                      BigButton LittleButton

Being 'Button' an abstract class or an interface.
I mean, how do I define an interface? Must I use modules?

If Button is a like a Java interface (i.e. no behavior), then you don't
need one in Ruby. Just implement BigButton and LittleButton with
compatible methods.

Well I'm trying to get rid of my way of thinking in Java and C++. I have modeled
a class that has objects of LittleButton and BigButton.
In Java I'd have:

class Window {
  private Button little = new LittleButton();
  private Button big = new BigButton();
}

I know that in Ruby I won't declare attributes like that but it's hard to me
to have a code that dosen't seems to my model.

What do you mean with compatible methods?

How did I define the interface? The comment above the method. No, I'm not kidding.

Yes, I understand what you mean.

need to share some implementation. However, in Ruby loosen your strangle hold on interface. "Free your mind." :wink:

Haha, yeah, that's what I want to achieve, I'm trying it but is's hard
for me like Java/C++ developer.

Thanks to all for the answers.

One other use case:

widgets.each {|w| w.bg = 0xffffff if Button === w}

martin

···

James Edward Gray II <james@grayproductions.net> wrote:

Obviously, there are great uses for classes and modules when you do
need to share some implementation. However, in Ruby loosen your
strangle hold on interface. You'll be surprised what it can do for you.

How did I define the interface? The comment above the method. No,
I'm not kidding.

Doesn't this make it very difficult to write frameworks where you often
need to define an 'interface' that extensions should implement in order
to plug into the framework?

A practical example of this came up on the Nitro/Og mailing list where
someone asked if there was any support for the Firebird database. The
reply indicated that there wasn't but that the OP was welcome to
contribute a 'Store' that the Og framework could use to interact with
such a database.

In other words, the Og framework needs to define (not necessarily in
code) what implementaters of a 'Store' should be providing. In Java
this could be acheived by either defining an abstract base class or
(preferrably) an interface. This specifies the 'contract' that the
framework expects a valid 'Store' instance to support.

From what you're saying, the answer in Ruby is to examine the code

and/or the documentation, which is reasonable enough, but, it does seem
to make it much more difficult to extend frameworks written in Ruby.
Particularly since you wouldn't know whether you'd missed a method
until you attempted to run some code.

Some time ago, I posted a similar problem. Check the following link:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/127973

Cheers,
Ed

···

On 7/22/05, Jim Weirich <jim@weirichhouse.org> wrote:

EdUarDo said:
> Hi all again :),
>
> How could I implement this model?
>
> Window <>--------------------- Button
> ^
> >
> >
> -----------------
> > >
> BigButton LittleButton
>
>
> Being 'Button' an abstract class or an interface.
> I mean, how do I define an interface? Must I use modules?

If Button is a like a Java interface (i.e. no behavior), then you don't
need one in Ruby. Just implement BigButton and LittleButton with
compatible methods.

If there is shared code in Button, then you can (1) create a class Button
and inherit from it in BigButton and LittleButton, or (2) Create a Button
module and include it in both Big and Little Buttons.

--
Encontrá a "Tu psicópata favorito" http://tuxmaniac.blogspot.com
  
Thou shalt study thy libraries and strive not to reinvent them without cause,
that thy code may be short and readable and thy days pleasant and productive.
-- Seventh commandment for C programmers

EdUarDo said:

If Button is a like a Java interface (i.e. no behavior), then you don't
need one in Ruby. Just implement BigButton and LittleButton with
compatible methods.

Well I'm trying to get rid of my way of thinking in Java and C++. I have
modeled a class that has objects of LittleButton and BigButton.
In Java I'd have:

class Window {
  private Button little = new LittleButton();
  private Button big = new BigButton();
}

Ruby:

  class Window
    def initialize
      @little = LittleButton.new
      @big = BigButton.new
    end
  end

I know that in Ruby I won't declare attributes like that but it's hard to
me to have a code that dosen't seems to my model.

Hmmm ... I'm not sure I understand the last half of that sentence.

What do you mean with compatible methods?

If you want to be able to use either Big or Little buttons in the same
piece of code, then both buttons need to respond to a common set of
methods. The methods in this common set should be named the same in both
classes, take the same number of arguments and have similar semantics.

···

--
-- Jim Weirich jim@weirichhouse.org http://onestepback.org
-----------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)

I can honestly say that I never try to sit down and implement a Java Interface without reading the documentation. :wink: So it's not really a change for me.

Now, if I botch my implementation, Java *may* catch it faster (it depends on the mistake I make). Eventually though, both should just blow up, and I'll see the problem then.

In exchange, Ruby sets me free to try what I think is a great idea, though the author never considered it. I know what's expected of the object I'm passing and as long as mine behaves that way, the rest of the details are irrelevant.

I guess it's always about trade offs.

James Edward Gray II

···

On Jul 26, 2005, at 11:06 AM, redentis wrote:

From what you're saying, the answer in Ruby is to examine the code
and/or the documentation, which is reasonable enough, but, it does seem
to make it much more difficult to extend frameworks written in Ruby.
Particularly since you wouldn't know whether you'd missed a method
until you attempted to run some code.

redentis wrote:

From what you're saying, the answer in Ruby is to examine the code
and/or the documentation, which is reasonable enough, but, it does seem
to make it much more difficult to extend frameworks written in Ruby.
Particularly since you wouldn't know whether you'd missed a method
until you attempted to run some code.

This sounds like a good use for unit tests, if you ask me.

absolutely. plus, it's easy enough to check:

   harp:~ > cat a.rb
   module Interface
     MUST = %w(
       foo
       bar
       foobar
     )
     class << self
       def included other
         MUST.each{|m| raise "must have ##{ m }" unless other.instance_methods.include? m}
         super
       end
     end
   end

   class C
     def foo; end
     def bar; end

     include Interface
   end

   harp:~ > ruby a.rb
   a.rb:10:in `included': must have #foobar (RuntimeError)
           from a.rb:10:in `each'
           from a.rb:10:in `included'
           from a.rb:20:in `include'
           from a.rb:20

the built-in Enumerable module requires an interface - that of 'each' and '<=>'
and it seems successfull enough....

cheers.

-a

···

On Wed, 27 Jul 2005, Charles Steinman wrote:

redentis wrote:

From what you're saying, the answer in Ruby is to examine the code
and/or the documentation, which is reasonable enough, but, it does seem
to make it much more difficult to extend frameworks written in Ruby.
Particularly since you wouldn't know whether you'd missed a method
until you attempted to run some code.

This sounds like a good use for unit tests, if you ask me.

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
My religion is very simple. My religion is kindness.
--Tenzin Gyatso

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