11年的软件老兵教你Ruby进阶!!!【需静心细读】

419 查看

原文标题:对程序员最友好的,可读性最强的语言:Ruby: 3. 进阶知识

欢迎大家继续跟我学习Ruby. 接下来我为大家介绍一些Ruby 不会让人第一眼就弄明白的知识! 也是进阶知识!

Ruby中的简写形式

初学者看到Ruby中的简写,立马蒙圈了.


give "我", :what => '咖啡', :count => '2', :unit => '杯' do
  "味道不错哟!"
end

上面的代码, 会让没有接触过ruby的同学不明就里. 我就问一个问题:

上面的 give 函数有几个参数?

简写1: 方法调用的最外层括号可省略

puts "hihihi"   # 等同于   puts("hihihi")
简写2: 函数最后一行默认有return

每个函数的最后一行默认是返回值,是不需要写return的


def color
  'red'   # 等同于 return 'red'
end
简写3: hash

hash最外面的{} 在大多数情况下可以省略


Apple.create :name => 'apple', :color => 'red'

#等同于:
Apple.create({:name => 'apple', :color => 'red'})

#等同于hash的另一种写法: 
Apple.create name: 'apple', color: 'red'
简写4: 调用block

调用某个block中的某个方法:


Apple.all.each  {  apple      apple.name  }

# 等同于:
Apple.all.map(&:name)
Module

它用来把各种方法提炼出来,供其他 class 引用.

  • 不能被new
  • 可以被include
  • module中的 self.xx方法可以被直接调用
  • module中的普通方法,需要被某个class include之后, 由对应的class调用.

# tool.rb

module Tool

  # 这个方法无法直接运行.
  def show_tip
    "this is the tip"
  end

  # 这个方法可以通过 Tool.say 来运行,
  def self.say
    "hi"
  end
end

Tool.say   #=>  "hi", 这个时候,Tool.say就是一个class method.
Tool.new.show_tip  #=> 会报错  module.rb:11:in `<main>': undefined method `new' for Tool:Module (NoMethodError)
Mixed In: 可以被作为mixed in 使用.

mixed in 是一种比 继承interface/implementation 更加优秀的存在. 非常直观, 而且很好的重用了代码.

我们来定义两个class, StudentTeacher. 下面可以看到, 这两个类,通过include, 都继承了 Tool module的方法: show_tip:


require './tool.rb'

class Student
  include Tool
end

Student.new.show_tip  # => "this is the tip"

class Teacher
  include Tool
end

Teacher.new.show_tip  # => "this is the tip"

不要小瞧这个能力, 它用非常简洁的方式, 完成了其他语言难以完成的事情.

元编程初探

元编程, meta programming, 是一种特别强大的功能. 举个例子:


def say_hi_to_jim
  "hi, jim"
end
def say_hi_to_li_lei
  "hi, li_lei"
end
def say_hi_to_han_mei_mei
  "hi, han_mei_mei"
end

这三个方法, 也可以这样写:


['jim', 'li_lei', 'han_mei_mei'].each do name
  define_method "say_hi_to_#{name}" do
    puts "hi, #{name}"
  end
end

然后就可以调用了:

say_hi_to_jim  # => 'hi, jim'

每个语言都多少有些动态改变代码逻辑的能力, 但是Ruby的元编程能力是最强的. 用起来也是最得心应手的.

ruby 元编程可以让我们做到其他传统语言无法做到的事. 大家务必知道他的重要性.

可以先不学, 但是要知道它的作用.

Rails框架之所以能这么强大, 全靠ruby的元编程能力.

推荐一本书: <<Ruby 元编程>>

如何查看api
  • 查看ruby API 很其他的语言差不多.官方文档是:api.ruby-lang.org
  • 多google,
  • 知道方法的基本用法
  • 有翻墙工具.
ruby DEBUG 之调试信息

ruby的出错信息, 距离顺序是从上到下,时间顺序是从下到上,出现的.例如:


test_class.rb:8:in `extend': wrong argument type Class (expected Module) (TypeError)
  from test_class.rb:8:in `<class:Child>'
  from test_class.rb:7:in `<main>'

上面信息中,时间的运行顺序是,先运行 test_class.rb的第7行,再运行到第8行,才出错. 出错信息是 wrong argument type Class (expected Module) (TypeError)

在调试中,class instance 的最外层是#<> 的固定格式,前面的Apple表示class名字,0x00000001f0dad8 是内存的地址. 例如:#<Apple 0x00000001f0dad8>

双冒号 ::

表示 class的 常量


class Interface
  class Apple
    COLOR = 'red'
  end
end

puts Interface::Apple::COLOR

:: 也表示命名空间


# rails中:

app/controller/interface/apples_controller的话:

class Interface::ApplesController < ApplicationController::Base
  ## 其他代码
end
代码块: block, proc, lambda

几乎是一样的. 都表示代码块儿.

ruby的代码块儿是相比其他传统语言特别强大的功能. 碾压其他传统语言.

例子:


[1,2,3].each { e puts e }

# 假设student有两个属性:name, age
Student.all.map { student
  {
    :name => student.name,
    :aget => student.age
  }
}
block 最后一行代码默认是返回值.

[1,2,3].map { e
  "#{e}#{e}"   # 这里是block的最后一行,默认是被return 的.
}

# => ["11", "22", "33"]

下面这样写,会报错:


[1,2,3].map { e
  return "#{e}#{e}"
}

# => in `block in <main>': unexpected return (LocalJumpError)
do ...end 与 { } 几乎是一样的.

可以认为下面两个代码相同

[1,2,3].each { e
  puts e
}

[1,2,3].each do e
  puts e
end

一个方法最多只有一个参数是 block, 并且永远是参数的最后一位.

回到 "简写" 这一节最初的问题:


give "我", :what => '咖啡', :count => '2', :unit => '杯' do
  "味道不错哟!"
end

从这里,可以看出:

最初的问题:几个参数?

其实是有三个参数:


give(
  "我",  # => 第一个参数,是一个 string
  {:what => '咖啡', :count => '2', :unit => '杯'},  # => 第二个参数,是个hash
  do "味道不错哟!" end   # => 这是第三个参数,是一个block. 也是最后一个参数
)

好了, 我们很快的过了一次Ruby的语法. 到这里,基本上高级的语法大家见识了大部分. 还有些特别罕见的语法, 平时我们写Rails代码时用不到, 只有在参与开源项目时, 实现各种框架时,才会用到,例如元编程, 例如一些精妙的写法,小技巧 等等. 我就不一一举例了. 如果大家希望在Ruby的世界里深造的话, 务必要读 << ruby meta programming>> 这本书. 极其深入.

最后,大家务必要把这三节课中的 例子,亲手敲一敲, 这样才有感悟!