Abstract class or interface?

Discussion in 'Ruby' started by EdUarDo, Jul 22, 2005.

  1. EdUarDo

    EdUarDo Guest

    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, Jul 22, 2005
    #1
    1. Advertising

  2. EdUarDo

    Jim Weirich Guest

    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.

    --=20
    -- Jim Weirich 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)
    Jim Weirich, Jul 22, 2005
    #2
    1. Advertising

  3. EdUarDo

    EdUarDo Guest

    > 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?
    EdUarDo, Jul 22, 2005
    #3
  4. EdUarDo <> 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 =E2=80=98foo=E2=80=99 on an object that does not
    understand =E2=80=98foo=E2=80=99, Ruby doesn't care.

    This is what people mean when they talk about =E2=80=9Cduck typing=E2=80=9D=
    :
    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

    --=20
    Daniel Brockman <>

    So really, we all have to ask ourselves:
    Am I waiting for RMS to do this? --TTN.
    Daniel Brockman, Jul 22, 2005
    #4
  5. 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?


    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." ;)

    James Edward Gray II
    James Edward Gray II, Jul 22, 2005
    #5
  6. EdUarDo

    Jim Weirich Guest

    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 hav=

    e
    > modeled a class that has objects of LittleButton and BigButton.
    > In Java I'd have:
    >
    > class Window {
    > private Button little =3D new LittleButton();
    > private Button big =3D new BigButton();
    > }


    Ruby:

    class Window
    def initialize
    @little =3D LittleButton.new
    @big =3D 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.

    --=20
    -- Jim Weirich 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)
    Jim Weirich, Jul 22, 2005
    #6
  7. EdUarDo

    EdUarDo Guest

    > 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." ;)


    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.
    EdUarDo, Jul 23, 2005
    #7
  8. James Edward Gray II <> 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.


    One other use case:

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

    martin
    Martin DeMello, Jul 25, 2005
    #8
  9. EdUarDo

    redentis Guest

    > 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.
    redentis, Jul 26, 2005
    #9
  10. 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.


    I can honestly say that I never try to sit down and implement a Java
    Interface without reading the documentation. ;) 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
    James Edward Gray II, Jul 26, 2005
    #10
  11. 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.
    Charles Steinman, Jul 26, 2005
    #11
  12. EdUarDo

    Ara.T.Howard Guest

    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.


    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
    --
    ===============================================================================
    | 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
    ===============================================================================
    Ara.T.Howard, Jul 26, 2005
    #12
  13. On 7/22/05, Jim Weirich <> wrote:
    >=20
    > 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?

    >=20
    > 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.
    >=20
    > 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.
    >=20


    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
    --=20
    Encontr=E1 a "Tu psic=F3pata favorito" http://tuxmaniac.blogspot.com
    =09
    Thou shalt study thy libraries and strive not to reinvent them without caus=
    e,
    that thy code may be short and readable and thy days pleasant and productiv=
    e.
    -- Seventh commandment for C programmers
    Edgardo Hames, Jul 26, 2005
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Matthias Kaeppler
    Replies:
    1
    Views:
    436
    R.F. Pels
    May 22, 2005
  2. Sameer
    Replies:
    4
    Views:
    600
    Roedy Green
    Aug 31, 2005
  3. Uzytkownik
    Replies:
    3
    Views:
    592
    Uzytkownik
    Apr 3, 2005
  4. Iyer, Prasad C

    Abstract Methods & Abstract Class

    Iyer, Prasad C, Oct 20, 2005, in forum: Python
    Replies:
    0
    Views:
    532
    Iyer, Prasad C
    Oct 20, 2005
  5. Replies:
    4
    Views:
    811
    Rolf Magnus
    May 17, 2006
Loading...

Share This Page