`
boyjunqiang
  • 浏览: 31994 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

《Rails for Java Developers》读书笔记1

阅读更多
书名:《Rails for Java Developers》英文版PDF
所处章节:第二章 Programming Ruby
页数范围:38~71

Java/Ruby语法特性对比:
Java divides the world into primitive types and objects. The primitive
types represent numeric values of various ranges and precision:
int i;


primitive types can use infix math, for example:
1+1;


To represent arbitrarily large integers, Java uses the BigInteger class: 
BigInteger twobil = new BigInteger("2000000000");


BigInteger cannot use infix mathematical notation you have
to say:
a.multiply(b)


Ruby transparently uses
the appropriate type as needed, Notice that x smoothly shifts from Fixnum to Bignum as necessary:
irb(main):004:0> x = 10**9
=> 1000000000
irb(main):005:0> x.class
=> Fixnum
irb(main):006:0> x *= 100
=> 100000000000
irb(main):007:0> x.class
=> Bignum

irb(main):018:0> 1.0.finite?
=> true
irb(main):019:0> (1.0/0.0).finite?
=> false


"?" by convention it is used for methods that return a
boolean

print(String.format("Hello, %s", name.toUpperCase()));

irb(main):005:0> "Hello, #{name.upcase}"
=> "Hello, READER"


In Java, you can use backslash escapes to represent characters:
print(String.format("Hello, \"%s\"\nWelcome to Java", name));

Ruby also uses backslash escapes:
irb(main):008:0> puts "Hello, \"#{name}\"\nWelcome to Ruby"
Hello, "Reader"
Welcome to Ruby


with %Q you can get rid of all these backslash escapes:
irb(main):011:0> puts %Q{"One", "Two", and "Three" are strings"}
"One", "Two", and "Three" are strings"


assertEquals('H', "Hello".charAt(0));

irb(main):015:0> ?A
=> 65
irb(main):019:0> ?H == "Hello".slice(0)
=> true
irb(main):022:0> ?o == "Hello"[-1]
=> true
irb(main):025:0> "Hello"[1,4]
=> "ello"


To turn off string interpolation,use a single-quoted string instead of a double-quoted one:
irb(main):028:0> "Hello, #{name.upcase}"
=> "Hello, READER"
irb(main):029:0> 'Hello, #{name.upcase}'
=> "Hello, \#{name.upcase}"


Java:
print("one\ntwo\nthree");

Ruby provides an explicit syntax for multiline strings called a here
document, or heredoc.
irb(main):035:0> puts <<MY_DELIMITER
irb(main):036:0" one
irb(main):037:0" two
irb(main):038:0" three
irb(main):039:0" MY_DELIMITER
one
two
three



Java:
public static String bleep(String input) {
return input.replaceAll("\\b\\w{4}\\b", "(bleep)");
}

Ruby use regular expressions, delimiting them with //:
irb(main):041:0> 'Are four letter words mean?'.gsub(/\b\w{4}\b/, "(bleep)")
=> "Are (bleep) letter words (bleep)?"


print("HELLO".toLowerCase());

irb(main):047:0> "HELLO".downcase()
=> "hello"
irb(main):048:0> "HELLO".downcase
=> "hello"


print(Math.cos(0));

irb(main):051:0> Math.cos(0)
=> 1.0
irb(main):051:0> Math.cos 0
=> 1.0


In Java, objects are type-safe. Objects know what they are capable of, type-safe and you cannot ask them to perform methods they do not have:
print("hello".cos(0));

Ruby objects are also type-safe:
irb(main):057:0> "hello".cos 0
NoMethodError: undefined method ‘cos' for "hello":String
from (irb):57


Type Safety Does Not Ensure Correctness!!!

public class PrintArgs {
public static void main(String[] args) {
for (int n=0; n<args.length; n++) {
System.out.println(args[n]);
}
}
}

ARGV.each {|x| puts x}
or
ARGV.each do |x|
puts x
end

$ ruby samples/print_args.rb one two three
one
two
three

irb(main):009:0> ['C', 'Java', 'Ruby'].each {|lang| puts "#{lang} is fun!"}
C is fun!
Java is fun!
Ruby is fun!
=> ["C", "Java", "Ruby"]

irb(main):002:0> ['C', 'Java', 'Ruby'] == %w{C Java Ruby}
=> true

irb(main):002:0> [1,2] + [3]
=> [1, 2, 3]
irb(main):003:0> [1,2,3] * 2
=> [1, 2, 3, 1, 2, 3]
irb(main):004:0> [1,2,1] - [2]
=> [1, 1]
irb(main):005:0> [1,2] / 2
NoMethodError: undefined method ‘/' for [1, 2]:Array
from (irb):5

irb(main):006:0> skills = ['C', 'Java']
=> ["C", "Java"]
irb(main):007:0> skills.push 'Ruby'
=> ["C", "Java", "Ruby"]
irb(main):008:0> skills.pop
=> "Ruby"


import java.util.*;
public class PrintEnv {
public static void main(String[] args) {
Map map = System.getenv();
for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
Map.Entry e = (Map.Entry) it.next();
System.out.println(String.format("%s: %s", e.getKey(), e.getValue()));
}
}
}

ENV.each {|k,v| puts "#{k}: #{v}"}

irb(main):037:0> dict = {:do => "a deer", :re => "a drop of golden sun"}
=> {:do=>"a deer", :re=>"a drop of golden sun"}

irb(main):013:0> dict.fetch(:do)
=> "a deer"
irb(main):014:0> dict.store(:so, "a needle pulling thread")
=> "a needle pulling thread"

irb(main):015:0> dict[:so]
=> "a needle pulling thread"
irb(main):016:0> dict[:dos] = "a beer"
=> "a beer"


import java.util.Map;
public class ForEach {
public static void main(String[] args) {
for (String arg: args) {
System.out.println(arg);
}
for (Map.Entry entry: System.getenv().entrySet()) {
System.out.println(
String.format("%s : %s", entry.getKey(), entry.getValue()));
}
}
}

irb(main):017:0> [1,2,3,4,5].collect {|x| x**2}
=> [1, 4, 9, 16, 25]

irb(main):021:0> [1,2,3,4,5].find_all {|x| x%2==0}
=> [2, 4]


We want to make two important points from these examples:
• Languages evolve and improve over time. Usually improvement
comes not from thin air but from ideas that have already been
explored elsewhere. Java’s For-Each syntax was inspired by other
languages that have similar features. The programmers who facilitate
this kind of cross-pollination are those who become fluent in
multiple programming languages.
• Languages evolve at many levels. Runtimes can change, language
syntax can change, and libraries can change. In Java, iteration
changes like the addition of For-Each are language changes. Similar
changes in Ruby are library changes, since each et. al. are
method calls. Library changes are easier to make than language
changes. (Many developers write libraries, few developers write
languages, and language evolution tends to be retarded by standards
bodies, backward compatibility, and so on.) Merely pointing
out that Java and Ruby enable different approaches to change is
not a value judgment. However, it may lead to value judgments
in a specific context (which you must provide). What parts of your
system need to change? On what timeline, and under whose direction?
Conversely, what parts need to stay rock-solid stable and be
guaranteed to work in the same fashion across different projects
over time?

if (n > 5) {
print("big");
} else {
print("little");
}

if n>5
puts "big"
else
puts "little"
end

or

puts(if (n>5)
"big"
else
"little"
end)


if (o != null) {
print("got o");
}

o = nil
puts o ? true : false

if lines > 1; puts "you have more than one line"; end

puts "you have more than one line" if lines > 1

puts "you've got lines" if lines != 0
puts "you've got lines" unless lines == 0

The following program runs an input loop, shouting back everything passed via stdin:
line = ""
puts "Shouting back #{line.upcase}" while line=gets


The ugliness here comes from using the boolean operator || to shoehorn
two statements into one to conform to the requirements of the statement
modifier form.
irb(main):026:0> i=1; puts(i*i) || i+=1 while i<=5
1
4
9
16
25

(1..5).each {|x| puts x*x}

irb(main):014:0> (1..10).max
=> 10
irb(main):015:0> (1...10).max
=> 9
irb(main):016:0> (1..10).exclude_end?
=> false
irb(main):017:0> (1...10).exclude_end?
=> true

("A".."C").each {|x| puts x*5}
AAAAA
BBBBB
CCCCC

irb(main):003:0> ('A'..'I').step(2) {|x| print x}
ACEGI


public static int numberGrade(char letter) {
switch(letter) {
case 'a':
return 100;
case 'b':
return 90;
case 'c':
return 80;
case 'd':
return 70;
case 'e':
case 'f':
return 0;
}
return 0;
}

def number_grade(letter)
case letter
when 'A': 100
when 'B': 90
when 'C': 80
when 'D': 70
else 0
end
end

def letter_grade(x)
case x
when 90..100: 'A'
when 80..90: 'B'
when 70..80: 'C'
when 60..70: 'D'
when Integer: 'F'
when /[A-F]/: x
else raise "not a grade: #{x}"
end
end

irb(main):018:0> case('John')
irb(main):019:1> when('John'): 'a name'
irb(main):020:1> when(String): 'a word'
irb(main):021:1> end
=> "a name"

You can also invoke the case equality operator directly; it is written as
a triple equals (===):
irb(main):002:0> (90..100) === 95
=> true
irb(main):003:0> (90..100) === 95.5
=> true
irb(main):004:0> (90..100) === 0
=> false
irb(main):005:0> Integer === 95
=> true
irb(main):006:0> Integer === 95.5
=> false


public class Person {
private String firstName;
private String lastName;

class Person

That’s it. There is no need to declare instance variables (the Ruby equivalent
of fields) because they come into existence automatically when
they are used.Ruby instance variables are
implicitly private, so this designation is unneeded as well.

Defining Constructors
In Java, Notice that the constructor
arguments share the same names as the private fields: firstName and
lastName. To disambiguate, you explicitly prefix the instance variables
with this.
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}

In Ruby, instance
variables must begin with a @, so there is no danger of a name collision
with method parameters.
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end


public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFullName() {
return String.format("%s %s", firstName, lastName);
}

attr_accessor :first_name, :last_name
def full_name
"#{first_name} #{last_name}"
end

Ruby also provides attr_reader and attr_writer if you want read-only
or write-only properties.

p.first_name = 'Justin'
p.last_name = 'Gehtland'
puts "Hello from #{p.first_name}"


To a Java eye, this looks like direct access to the fields first_name and
last_name, but in Ruby these are method calls. Even the punctuation (=)
is part of a method name. To make this clearer, here is a hand-coded
version of the accessors:
# don't do this--use attr_accessor!
def first_name
@first_name
end
def first_name=(new_name)
@first_name = new_name
end


public void marry(Person other) {
String newLastName =
String.format("%s-%s", getLastName(), other.getLastName());
setLastName(newLastName);
other.setLastName(newLastName);
}

def marry(other)
other.last_name = self.last_name = "#{self.last_name}-#{other.last_name}"
end

If you forget to prefix a setter with self, you may create hard-to-find
bugs. Java does not suffer from this ambiguity, so be careful.


Sometimes methods apply to a class as a whole, instead of to any particular
instance of a class. In Java these are called static methods:
public static String getSpecies() {
return "Homo sapiens";
}

In Ruby, these methods are called class methods:
def self.species
"Homo sapiens"
end


public class Person {
private String firstName;
private String lastName;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFullName() {
return String.format("%s %s", firstName, lastName);
}
public void marry(Person other) {
String newLastName =
String.format("%s-%s", getLastName(), other.getLastName());
setLastName(newLastName);
other.setLastName(newLastName);
}
public static String getSpecies() {
return "Homo sapiens";
}
}

class Person
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end
attr_accessor :first_name, :last_name
def full_name
"#{first_name} #{last_name}"
end
def marry(other)
other.last_name = self.last_name = "#{self.last_name}-#{other.last_name}"
end
def self.species
"Homo sapiens"
end
end



The == operator tests for identity. Strings s1 and s2 are == because they
point to the same object. Strings3 is not== to the others. It contains the
same characters, but it is at a different location in memory.
The equals method tests equality, which Java strings define to mean
“containing the same characters.” Thus, string s3.equals the others.
public void testEquals() {
String s1 = "Java rocks!";
String s2 = s1;
String s3 = new String("Java rocks!");
assertTrue(s1 == s2);
assertFalse(s1 == s3);
assertTrue(s1.equals(s3));
}

Ruby also distinguishes between identity and equality. Each unique
object has an object_id. Two objects are identical if they have the same
object_id, and the equal? method tests for this:
irb(main):001:0> s1 = s2 = "Ruby rocks!"
=> "Ruby rocks!"
irb(main):002:0> s1.object_id
=> 190400
irb(main):003:0> s2.object_id
=> 190400
irb(main):004:0> s2.equal? s1
=> true

irb(main):006:0> s3 = "Ruby rocks!"
=> "Ruby rocks!"
irb(main):007:0> s4 = "Ruby rocks!"
=> "Ruby rocks!"
irb(main):008:0> s3==s4
=> true
irb(main):009:0> s3.eql? s4
=> true
irb(main):010:0> s3.equal? s4
=> false

Java’s == tests for identity, while Ruby’s ==
usually tests for equality



import java.util.*;
public class AccessMe {
private String name;
private List stuff;
public AccessMe(String name) {
this.name = name;
stuff = new ArrayList();
}
public String getName() {
return name;
}
protected List getStuff() {
return stuff;
}
private void clear() {
name = null;
stuff = null;
}
}

Ruby does not have any equivalent for package private but supports
public, protected, and private:
class AccessMe
def initialize(name)
@name = name
@stuff = []
end
attr_accessor :name
protected
attr_accessor :stuff
private
def clear
@name = @stuff = nil
end
end


Although access control specifiers set a general rule for how you can
use a class, the general rule may need to bend in some circumstances.
For example, an object serializer may bypass protection modifiers to
access all of an object’s state. In Ruby, you can bypass access control
specifiers with send:
a = AccessMe.new("test")
a.send :stuff=, 'some stuff'
puts a.send(:stuff)


You can invoke
the access control methods more than once for the same symbol. At first
glance this may seem silly—why would a class want to have different
levels of access control at different times? One possibility is temporarily
setting methods public so that unit tests can test them:
def test_clear
AccessMe.send :public, :clear, :stuff
a = AccessMe.new("test")
a.clear
assert_nil a.stuff
end

This sample uses only techniques we have covered thus far. You can
use cleaner ways to set methods public for the duration of a test. One
approach is to use the extend method, described in Section 3.8, Mixins,
on page 90.

try {
methodThatOpensFile();
} catch (FileNotFoundException fnfe) {
System.out.println("File not found " + fnfe);
} catch (Exception e) {
System.out.println("Caught " + e);
}

begin
File.read 'nonexistent'
rescue SystemCallError => e
puts 'system call failed'
rescue Exception => e
puts 'generic failure of some kind'
else
puts 'nothing failed'
ensure
puts 'this always executes'
end

begin
1/0
rescue Exception => e
puts "Message " + e.message
puts "Backtrace " + e.backtrace.join("\n")
end

0
0
分享到:
评论

相关推荐

    Pragmatic.Bookshelf.Rails.for.Java.Developers.Feb.2007

    《Rails for Java Developers》是一本专为Java开发者撰写的书籍,旨在帮助他们快速掌握Ruby on Rails框架。本书由Stuart Halloway和Justin Etheredge合著,并于2007年2月出版。该书的目标读者是那些对Ruby on Rails...

    Ruby on Rails for PHP and Java Developers(2007.8).part1.rar

    Ruby on Rails for PHP and Java Developers(2007.8).part1.rar

    Ruby on Rails for PHP and Java Developers(2007.8).part4.rar

    Ruby on Rails for PHP and Java Developers(2007.8).part4.rar

    Ruby on Rails for PHP and Java Developers(2007.8).part3.rar

    Ruby on Rails for PHP and Java Developers(2007.8).part3.rar

    Ruby on Rails for PHP and Java Developers(2007.8).part2.rar

    Ruby on Rails for PHP and Java Developers(2007.8).part2.rar

    Rails for .NET Developers (Facets of Ruby)

    **标题与描述解析:** 本书《Rails for .NET Developers》旨在为已有.NET开发经验的学习者提供一条快速上手Ruby on Rails(简称RoR)的路径。通过本书,读者不仅能够学习到Ruby语言的基础知识及其面向对象编程的特点...

    ruby on rails for dummies

    《Ruby on Rails for Dummies》是一本专门为初学者设计的Ruby on Rails教程,它旨在帮助新手快速理解并掌握这个强大的Web开发框架。Ruby on Rails(简称Rails)是基于Ruby编程语言构建的一个开源Web应用程序框架,它...

    Rails for Zombies

    Rails for Zombies是一份面向初学者的教程,通过学习本教程,用户能够掌握创建Ruby on Rails应用程序的基本知识。 Rails for Zombies教程中的"Deep in the CRUD"部分深入讲解了CRUD(创建Create、读取Retrieve、...

    Pragmatic.Bookshelf.Rails.for.PHP.Developers

    Pragmatic.Bookshelf.Rails.for.PHP.Developers

    rails查询学习笔记

    标签 "源码" 暗示了这篇笔记可能会涉及到一些实际的代码示例,读者可以通过阅读源码来理解和学习Rails查询的细节。而 "工具" 可能指的是Rails中用于辅助查询的工具或gem,如ActiveRecord的 scopes 和 relations,...

    ruby on rails for eclipse开发插件

    ruby on rails for eclipse开发插件

    Ruby+for+Rails

    通过阅读"Ruby for Rails.pdf"和"Ruby on Rails 初体验.ppt",你可以深入了解Ruby on Rails的各个方面,包括其哲学、核心概念以及如何构建实际的Web应用程序。随着对Rails的理解加深,你将能够高效地开发出功能丰富...

    Rails相关电子书汇总二

    文件名称 "Rails for Java Developers.pdf" 明确指出,这本书是专门为Java开发者设计的,目标是帮助他们过渡到Rails开发。这意味着书的内容可能包括: 1. **Rails基础**:介绍Rails的核心概念,如MVC架构、...

    Ruby for Rails

    Ruby for Rails 英文原版, pdf格式 &lt;br&gt;本书是一部专门为Rails实践而写的经典Ruby著作,由四部分组成,共17章。第一部分讲述Ruby和Rails的编程环境。第二部分和第三部分与 Rails紧密联系,着重对Ruby这门语言...

    Agile Web Development with Rails for Rails 3.2

    ### Agile Web Development with Rails for Rails 3.2 #### 核心知识点概览 - **Rails 3.2概述** - **敏捷开发方法论** - **Model-View-Controller (MVC) 模式** - **Ruby on Rails基础与高级特性** - **面向对象...

    Ruby On Rails For Dummies

    ### Ruby on Rails For Dummies #### 核心知识点解析 **1. Ruby on Rails 概述** - **定义与特点**:Ruby on Rails(简称 Rails 或 RoR)是一种基于 Ruby 语言的开源 Web 应用框架,它采用了 Model-View-...

Global site tag (gtag.js) - Google Analytics