我本身有啥语言都会点,所以这门语言我会用其他语言的特性来描述,请谨慎阅读

基本概念

  • 注释 # =begin =end

  • 所有都是对象,要了解内嵌方法

    • 方法本身也是对象
    "Hello".method(:class).class #=> Method
    
    • 运算符号也是方法 可以用opertor dot来调用的
    1.+(3) #=> 4
    10.* 5 #=> 50 
    100.methods.include?(:/) #=> true
    
  • 控制流 所有控制块都用end结尾 条件不用括号

    • If - elsif - end 这个elsif有点离谱
    • while
    counter = 1
    while counter <= 5 do
      puts "iteration #{counter}"
      counter += 1
    end
    
    • for 经典语法糖
    for counter in 1..5
      puts "iteration #{counter}"
    end
    (1..5).each do |counter|
      puts "iteration #{counter}"
    end
      
    array.each do |element|
      puts "#{element} is part of the array"
    end
    hash.each do |key, value|
      puts "#{key} is #{value}"
    end
    

    这个each do后面的是lambda。就是语法有点怪异,c++的lambda

    std::vector<int> v;
    std::for_each(v.begin(),v.end(), [](int i){ std::cout<<i;});
    for(auto var : v) {
      std::cout<<var;
    }
    

    c++的lambda的参数比较明显,是个函数调用,ruby这个竖线包围有点不明不白, 更像range-for这种用法

    ruby甚至还有each_with_index

    # 如果你还需要索引值,可以使用 "each_with_index",并且定义
    # 一个索引变量
    array.each_with_index do |element, index|
      puts "#{element} is number #{index} in the array"
    end
    

    map reduce也是内嵌的。这点python也有,更泛型一些,而不是作为对象方法,ruby就是这么设计的

    array = [1,2,3,4,5]
    doubled = array.map do |element|
      element * 2
    end
    puts doubled
    #=> [2,4,6,8,10]
    puts array
    #=> [1,2,3,4,5]
    

    case when对应switch-case

    异常处理,python的try-except-finally对应begin-rescue-ensure

    begin
      raise NoMemoryError, 'You ran out of memory.'
    rescue NoMemoryError => exception_variable
      puts 'NoMemoryError was raised', exception_variable
    rescue RuntimeError => other_exception_variable
      puts 'RuntimeError was raised now'
    else
      puts 'This runs if no exceptions were thrown at all'
    ensure
      puts 'This code always runs no matter what'
    end
    
  • 函数 可以不用括号

def surround
  puts "{"
  yield
  puts "}"
end

surround { puts 'hello world' }

# {
# hello world
# }
# => nil

# 可以向函数传递一个块
# "&"标记传递的块是一个引用
def guests(&block)
  block.class #=> Proc
  block.call(4)
end

guests { |n| "You have #{n} guests." }
# => "You have 4 guests."

# 可以传递多个参数,这些参数会转成一个数组,
# 这也是使用星号符 ("*") 的原因:
def guests(*array)
  array.each { |guest| puts guest }
end
class Human

  # 一个类变量,它被这个类的所有实例变量共享
  @@species = "H. sapiens"

  # 基本构造函数
  def initialize(name, age = 0)
    # 将参数值赋给实例变量 "name"
    @name = name
    # 如果没有给出 age,那么会采用参数列表中的默认值
    @age = age
  end

  # 基本的 setter 方法
  def name=(name)
    @name = name
  end

  # 基本地 getter 方法
  def name
    @name
  end

  # 以上的功能也可以用下面的 attr_accessor 来封装
  attr_accessor :name

  # Getter/setter 方法也可以像这样单独创建
  attr_reader :name
  attr_writer :name

  # 类方法通过使用 self 与实例方法区别开来。
  # 它只能通过类来调用,不能通过实例调用。
  def self.say(msg)
    puts "#{msg}"
  end

  def species
    @@species
  end
end

对比c++来解释,@@是静态变量,实例共享主要是setter getter设计比较语法糖,齁得慌

继承 <

class Doctor < Human
end

包含和扩展,这个也是语法糖

# '包含'模块后,模块的方法会绑定为类的实例方法
# '扩展'模块后,模块的方法会绑定为类方法

class Person
  include ModuleExample
end

class Book
  extend ModuleExample
end

Person.foo     # => NoMethodError: undefined method `foo' for Person:Class
Person.new.foo # => 'foo'
Book.foo       # => 'foo'
Book.new.foo   # => NoMethodError: undefined method `foo'

一般都继承Stucture,类似python继承object


ref

  • https://learnxinyminutes.com/docs/zh-cn/ruby-cn/