This is a good explanation of duck typing. If you are still having
trouble
with it you might consider picking up a copy of: "Practical
Object-Oriented Design in Ruby??? By: Sandi Metz
Very good book easy to follow and excellent chapter on duck typing among
other handy features of object oriented design.
On Monday 02 June 2014 13:24:43, Roelof W. [email protected] wrote:
Can anyone then give me a hint how to solve this by duck typing ?
I have read many pages about it but I still confuses me.
With “traditional” object-oriented programming, a class is also a data
type. That meant: different class, different data type. If classes have
the
same ancestor or implement the same interface, they can be casted to
that
base class or interface. Basically, the common denominator. Whenever the
method you want to call is defined in that base class/interface, you can
call it, not matter what actual class you have.
Now, introduce duck typing. Duck typing has the popular slogan “If it
walks
like a duck, and quacks like a duck, I’ll happily treat it as a duck.”
That
means that there is no need for common base classes or interfaces any
more.
If classes A and B share the same method signature, you can call it on
both
classes, no matter what they otherwise do.
Consider, for example, two classes: A PDF writer and a network socket.
Suppose they both have the method “write(something)” defined. Now, the
two
classes do not share anything else. They have no common ancestor and
implement no common interface. In fact, they perform two completely
different tasks!
Somewhere in your program, you want to serialize a text. You call
“writer_object.write(my_text)”. But there are different code paths that
lead to this certain point, and in one case, you may end up with a PDF
writer object stored in the variable “writer_object”, and in anthoer
case,
it may be the socket.
In ruby, this works. The results are different, of course, but it works.
The vast advantage is that you can decide on your program’s behaviour
somewhere in your code, but have the very same method writing the text.
For example, there could be a user interface where the user could select
“Send Text via E-Mail” or “Print Text to PDF”. Based on that selection,
your code would instanciate either the Socket class or the PDF writer.
However, the other part of your code that is responsible for serializing
it
does not have to know about this choice, it just happily uses the
“write”
method.
A small code example of Duck Typing in action could look like this:
—%<—
[1] pry(main)> class A
[1] pry(main)* def quack()
[1] pry(main)* puts “Quaaa!”
[1] pry(main)* end [1] pry(main)* end => nil
[2] pry(main)> class B
[2] pry(main)* def quack()
[2] pry(main)* puts “Quack! Quack!”
[2] pry(main)* end [2] pry(main)* end => nil
[3] pry(main)> def do_quack(a_class)
[3] pry(main)* a_class.quack()
[3] pry(main)* end => nil
[4] pry(main)> do_quack(A.new)
Quaaa!
=> nil
[5] pry(main)> do_quack(B.new)
Quack! Quack!
=> nil
—>%—
As you can see, the “do_quack” method does not care whether its an
instance
of class A or class B it gets passed, it just calls the “quack” method.
And
in fact, it yields different results each time.
HTH.
--- Eric