ruby介绍

——李福@淘宝

fswordlee@twitter

http://weibo.com/fsword

介绍 Ruby

面向对象的设计

java中的对象

基本数据类型: int, float, boolean ...
java代码中的Object表示什么?
一个类?
那么 Object.class 又是什么呢?
另一个类?

似乎不太一致?

java中的对象

这段代码是否能统一处理各种对象?

public void dealWith( Object... objs ){
    System.out.println(objs.length);
}
dealWith( 1 )
dealWith( new int[]{ 1,2 })
dealWith( new Integer[]{ 1,2 })

Ruby: 一切都是对象

ruby-1.9.2-p290 :001 > iter = 5.times
 => #<Enumerator: 5:times> 
ruby-1.9.2-p290 :002 > iter.next
 => 0
ruby-1.9.2-p290 :003 > iter.next
 => 1

Ruby: 一切都是对象

"string".class  #  String 
"string".class.class  #  Class 
"string".class.superclass  #  Object 
"string".class.is_a? Module  #  true 
"string".class.is_a? Object  #  true 
1.class  #  Fixnum 
1.class.class  #  Class 
1.class.superclass  #  Integer 
1.class.superclass.superclass   #  Numeric 
1.class.superclass.superclass.superclass  #  Object 
nil.class  #  NilClass 
nil.class.class  #  Class 
nil.class.superclass  #  Object 
Class.superclass  #  Module 
Class.superclass.superclass  #  Object 
Object.superclass  #  BasicObject 
Object.superclass.superclass  #  nil 

Ruby: 一切都是对象

统一的对象模型

Ruby: 一切都是对象

关于多态
ruby支持override,但是不支持overload
//overload - java代码示例
public void doSth(Tom obj){...}
public void doSth(Jerry obj){...}
// ruby代码
def doSth(cartoon_figure) do cartoon_figure.doSth end
class Tom
  def doSth ... end
end
class Jerry
  def doSth ... end
end

开放类(open class)

开放类

需求:list.join(",")

java的做法

class ExtList implements List{ 
    ExtList(List innerList){...}
    public String join(String seperate){...}
}
现有代码全部需要重写,而且会导致ExtList有不同版本

open class的方式

class List
  def join ... end
end

开放类

需求:time.yesterday 
class Time
  def yesterday
    self - 86400
  end
end
需求:{:name => 'john', :age => 31}.only :name 
class Hash
  def only(*allowed)
    reject { |k,v| !allowed.include?(k) }
  end
end

理解模块(module)

模块的用途

命名空间
module A
  class People
    def say
      puts "hello"
    end
  end

  class Animal
    def say
      puts "mie...."
    end
  end
end

p = A::People.new
p.say # hello

模块的用途

多重继承
module A
  module People
    def say
      puts "hello"
    end
  end
  module Easter
    def eat
      puts 'eat'
    end
  end
end

class Chinese
  include A::People
  include A::Easter
end

p = Chinese.new
p.say # hello
p.eat # eat

singleton class

一个小例子

$ irb
1.9.3p194 :001 > class A;end
 => nil 
1.9.3p194 :002 > A.ancestors
 => [A, Object, Kernel, BasicObject] 
对象关系和继承图

可继承的"类方法"

# sample.rb
class Parent
  def self.make_call
    p "called from parent class"
  end
end

class Child < Parent
  def self.make_call
    super
    p "called from child Class"
  end
end
  
Parent.make_call
Child.make_call
$ ruby sample.rb 
"called from parent class"
"called from parent class"
"called from child Class"

block与声明式编程

ruby中的循环

原始形式(外部迭代器)
iter = 2.upto(5)
while iter.next
  p 'hello'
end
改为block(内部迭代器)
2.upto(5) do
  p 'hello'
end
支持参数
2.upto(5) do |i|
  p 'hello'+i
end

block的作用

先看一个群里的问题(groovy)
for(int i =0 ;i<10;i++){
  pool.submit({
    println i
  } as Runnable);
}
结果:
1
2
4
4
5
6
8
8
变量变化,不能按照预期工作

block的作用

我们看看java是怎么做的
for(int i = 0 ; i<10 ; i++){
  final int tempI = i;
  pool.submit(new Callable(){
    public Object call(){
      System.out.println(tempI); return null;
    }
  });
}
可以工作,但是增加了临时变量,不自然

block的作用

改进groovy的例子
(0..10).each{
  i -> pool.submit( { println i } as Runnable );
}
ruby的例子
(0..10).each{
  |i| pool.submit { print i };
}
也可以写成
(0..10).each do
  |i| pool.submit { print i };
end
总结:block使得变量局部化

block的作用:编程模式

指令式编程
List keywords  =  getSomeData();
Map> result = new HashMap<...>();
for (String  k:  keywords)  {
    char  firstChar = k.charAt(0);
    if  (!result.containsKey(firstChar))  {
        result.put(firstChar, new ArrayList());	
    }
    result.get(firstChar).add(k);
}
for  (List  list:  result.values())  {
     Collections.sort(list);
}
声明式编程
result = keywords.group_by{ |a| a[0..1] }

娱乐时间: 闭包与青年

娱乐时间: 闭包与青年

娱乐时间: 闭包与青年

娱乐时间: 闭包与青年

再看函数与对象

从项目里找一段代码

再看函数与对象

再看函数与对象

怎么写更好?

语言与设计模式

语言与设计模式

class MyFoo
    def method_missing(method, *args, &block)
        puts %Q[method: #{method}
args: #{args.inspect}
on: #{self.inspect}
]
    end
end
ruby-1.9.2-p290 :009 > foo = MyFoo.new
ruby-1.9.2-p290 :010 > foo.hello
method: hello
args: []
on: #<MyFoo:0x0000000144cbf8>
ruby-1.9.2-p290 :011 > foo.world
method: world
args: []
on: #<MyFoo:0x0000000144cbf8>

语言与设计模式

它能做什么?
ruby版代理模式
class MyProxy
    def initialize(real_account)
        @subject = real_account
    end

    def method_missing(name, *args)
        puts("Delegating #{name} message to subject.")
        @subject.send(name, *args)
    end
end

参考

亲,要学会翻墙哦 :-)

Q & A

/

#