Abstract class or interface?

E

EdUarDo

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

Jim Weirich

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 (e-mail address removed) http://onestepback.org
 
E

EdUarDo

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

Daniel Brockman

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?

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 <[email protected]>

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

James Edward Gray II

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
 
J

Jim Weirich

EdUarDo said:
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 (e-mail address removed) http://onestepback.org
 
E

EdUarDo

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.
 
M

Martin DeMello

James Edward Gray II said:
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
 
R

redentis

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.
 
J

James Edward Gray II

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
 
C

Charles Steinman

redentis said:
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.
 
A

Ara.T.Howard

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

Edgardo Hames

=20
EdUarDo said:
=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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top