O''''Reilly Network For Information About''''s Book part 20 pot - Pdf 17


6.2. Applying Some Structure
Both Ruby and Java are object-oriented languages. Both support object models
with single inheritance. Still, you're going to see some differences between Ruby
and Java:
Figure 6-1. Java programmers refactor the inside of a loop; code blocks let Ruby
developers refactor the outside of a loop, too

 In Java, the smallest application is a class. In Ruby, everything is an object,
so you can evaluate primitives, expressions, code blocks, and scripts. They
all are objects, and all are valid Ruby.
 In Java, class definitions are static. In Ruby, you can modify your classes on
the fly. When you see a class definition, if the class already exists, the new
definition will modify the class that's already there.
 Ruby supports mixins and Java does not. Think of a mixin as an interface,
plus an implementation, that you can attach to a class.

In Ruby, everything returns some value, and that value is typed dynamically,
so you won't see a return in the method definition.
 In Ruby, method parameters and instance variables are not typed; but the
instances themselves are typed.
For the most part, you can still use your OO design skills in Ruby as you did in
Java. You'll also see some common design patterns, like model-view-controller.
David Heinemeier Hansson: Ruby
Creator of Ruby on Rails

David Heinemeier Hansson is the programmer of Basecamp, Backpack,
and Ta-da List under the commercial banner of 37signals, but he's also
an avid open source contributor through the Rails web development
framework and Instikione of the most popular Ruby applications. He's
intensely focused on doing something about the sorry state of

Second, open classes. Active Record
consists of around 10 layers that are all
applied to the base class. It keeps the API
simple. You don't use 10 different classes,
and Rails still satisfies the requirement of a
maintainable code base. It's also been
helpful to be able to extend the base classes
and fix bugs in the standard library between
releases.
Third, everything is an object, with
exceptions. You can work procedurally on
top of the object orientation, but that's the
order of business. It makes for an incredibly
consistent experience that really makes
"The Principle of Least Surprise" come
true. You can guess the names and behavior
of Ruby classes more often than not.
What makes Java
limiting to you?
DHH: On an "every language can do
anything" level, there's nothing that
inherently limits what Java can do, but
there's certainly different comfort zones for
different languages and people. I can't stand
repeating myself. I can't stand a long
feedback cycle. I can't stand computing in
my head or writing by hand what the
compiler should be able to figure out from
my intentions.
Java doesn't make me a happy programmer;

@total -= x
end
end
You've declared three methods. Ruby will call initialize when it creates a
new object, such as this calculator. Notice that initialize defines an instance
variable called @total. In Ruby, instance variables start with @, class variables
start with @@, and global variable start with $. Now, in irb, you can load the file
and use the calculator.
irb(main):005:0> require 'Calculator'
=> true
irb(main):006:0> c=Calculator.new
=> #<Calculator:0x28b4a98 @total=0>
irb(main):007:0> c.add 100
=> 100
irb(main):008:0> c.subtract 40
=> 60
And it works, just like you'd expect. Ruby developers take advantage of open
classes . I'm going to change the definition of Calculator
, but keep in mind that
we still have c, an instance of Calculator. I actually open up the definition of
the class again like this:
irb(main):009:0> class Calculator
irb(main):010:1> def reset
irb(main):011:2> @total = 0
irb(main):012:2> end
irb(main):013:1> end
I just added a method called reset. I also could have changed an existing
method.
irb(main):014:0>
c.reset

Modules form the foundation of classes and mixins .
Mixins are not new. Smalltalk supported them back in 1971. Recall that a mixin is
an interface with an implementation. That means you can group together a set of
methods that many classes may need to use.
Look at this contrived little example. To build the friendliest possible application,
you may want to build a mixin to greet any object by name. You'd code it like this:

irb(main):021:0> module Greetable
irb(main):022:1> def greet
irb(main):023:2> puts "Hello, " + self.name
irb(main):024:2> end
irb(main):025:1> end
=> nil
Then, you can include this code in a class called Person:
irb(main):011:0> class Person
irb(main):012:1> include Greetable
irb(main):013:1> def initialize(name, age)
irb(main):014:2> @name=name
irb(main):015:2> @age=age
irb(main):016:2> end
irb(main):017:1> attr_reader :name
irb(main):018:1> end
=> nil
You can use this code in Person:
irb(main):039:0> person=Person.new("Bruce",40)
=> #<Person:0x2a970a0 @age=40, @name="Bruce">
irb(main):040:0> person.greet
Hello, Bruce
=> nil
While mixins seem interesting, this code probably smells wrong to you. Unless

garbled line at the bottom? It's actually "Person:0x28c1170 @age=40,
@name=\"Bruce\" in reverse. That's impressive. Now, you can add a mixin
that can inspect the class, and integrate the most intimate details of the class into
the mixin. And you can do all of this integration before a class even exists. I can
use mixins for things like security or persistence. Java developers often resort to
AOP to get the capability of mixins.
6.2.3. Interceptors
I've said that Java framework developers these days place an ever-increasing value
on techniques that change the behavior of an existing class, without changing its
code. One such technique is method interception . JBoss and Spring use method
interception to attach arbitrary services to a POJO. With Ruby, interception is easy.
You simply take a method, rename it, and put another method in its place (see
Figure 6-2).
For example, let's say that my friend, Dave Thomas, asks me to watch his laptop
for a few minutes before his big Ruby presentation. I could go to his Ruby shell
and enter this little gem based on an example from his book,
Figure 6-2. In Ruby, to do method interception, you simply rename and replace a
method, with the new implementation calling the old

Programming Ruby
(Pragmatic Bookshelf). This version intercepts new, as you
can see in Figure 6-2. I simply rename the original and call it from the replaceme
nt
new
. The interceptor will print out a message whenever Ruby creates a new object.
Here's how easy it is:
class Class
alias_method :original_new, :new
def new(*args)
result = original_new(*args)

and remoting.
Mixins
Java doesn't provide mixins, but you can simulate them with AOP.
David Heinemeier Hansson and Jim Weirich, Two Ruby Experts:
AOP in Ruby

Jim Weirich is a software consultant for Compuware. He has worked
with real-time data systems for testing jet engines, networking software
for information systems, and image processing software for the financial
industry. Jim is active in the Ruby community, contributing to several
Ruby projects including Rake and RubyGems.
Why
hasn't
AOP
taken off
for
Ruby?
DHH: A standardized AOP framework has never
really taken off in Ruby because the language itself
already su
pports most of the desirable functionality of
AOP.
The following is an example from Action Pack, the
controller/view part of Rails. And here follows the
code block that injects the layout functionality into
the original render method:
base.class_eval do
alias_method :render_without_layout, :render
alias_method :render, :render_with_layout
end


Nhờ tải bản gốc
Music ♫

Copyright: Tài liệu đại học © DMCA.com Protection Status