Ruby学习笔记

Ruby基础

print

#!/usr/bin/ruby -w
puts "S0:Hello, Ruby!"#自动换行
print "S1:Hello, Ruby!"
puts "S2:Hello, Ruby!"
print "S3:Hello",", ","Ruby!\n"
puts "S4:Hello",", ","Ruby!"
p "AAAA"

输出结果

S0:Hello, Ruby!
S1:Hello, Ruby!S2:Hello, Ruby!
S3:Hello, Ruby!
S4:Hello
, 
Ruby!
"AAAA"

Here Document

ruby的四种打印方法,挺有意思的,打印出<<后的字符串之前的内容。

  • 没有引号的字符串
  • 带引号的字符串“”
  • 通过执行区间内的命令``
  • 字符串组合,有无“”都可以
#!/usr/bin/ruby -w
# -*- coding : utf-8 -*-

print <<EOF
    这是第一种方式创建here document 。
    多行字符串。
EOF

print <<"EOF";                # 与上面相同
    这是第二种方式创建here document 。
    多行字符串。
EOF

print <<`EOC`                 # 执行命令
	echo hi there
	echo lo there
EOC

print <<"foo", <<"bar"	      # 您可以把它们进行堆叠
	I said foo.
foo
	I said bar.
bar

print <<fooo, <<barr	      # 您可以把它们进行堆叠
	I said fooo.
fooo
	I said barr.
barr

执行结果

    这是第一种方式创建here document 。
    多行字符串。
    这是第二种方式创建here document 。
    多行字符串。
hi there
lo there
	I said foo.
	I said bar.
	I said fooo.
	I said barr.

BEGIN END

BEGIN {
   code
}#在程序运行前执行
END {
   code
}#在程序运行后执行

变量

Ruby 支持五种类型的变量。

  • 一般小写字母、下划线开头:变量(Variable)。
  • $开头:全局变量(Global variable)。
  • @开头:实例变量(Instance variable)。
  • @@开头:类变量(Class variable)类变量被共享在整个继承链中
  • 大写字母开头:常数(Constant);定义在class或module内的常量可以被内部的function访问,定义在外的常量可以被全局访问。
  • 注意打印时要用“#”
#!/usr/bin/ruby

$global_value=100
class Customer
   @@no_of_customers=0
   def initialize(id, name, addr)
      @cust_id=id
      @cust_name=name
      @cust_addr=addr
   end
   def display_global_value()
      puts "Customer #@cust_id global_value #$global_value"
   end
   def display_details()
      puts "Customer id #@cust_id"
      puts "Customer name #@cust_name"
      puts "Customer address #@cust_addr"
   end
   def total_no_of_customers()
      @@no_of_customers += 1
      puts "Total number of customers: #@@no_of_customers"
   end
end

# 创建对象
cust1=Customer.new("1", "John", "Wisdom Apartments, Ludhiya")
cust2=Customer.new("2", "Poul", "New Empire road, Khandala")

# 调用方法
cust1.display_global_value()
cust2.display_global_value()
cust1.total_no_of_customers()
cust2.total_no_of_customers()

输出结果

Customer 1 global_value 100
Customer 2 global_value 100
Total number of customers: 1
Total number of customers: 2

Hash type

#!/usr/bin/ruby

hsh  = { "red" => 0xf00, "green" => 0x0f0, "blue" => 0x00f }
hsh.each do |key, value|
    print key, " is ", value, "\n"
end

function

  • 可变长度的参数
  • 无需例化,直接调用function
  • alias起别名 alias func1 func2
  • undef func1取消func1的定义
#!/usr/bin/ruby
# -*- coding: UTF-8 -*-
class Demo
	def sample (*test)
   		puts "参数个数为 #{test.length}"
   		for i in 0...test.length
      		puts "参数值为 #{test[i]}"
   		end
	end
	def Demo.dir_access()
		puts "YES!"
	end
end
demo1=Demo.new()
demo1.sample "Zara", "6", "F"
demo1.sample "Mac", "36", "M", "MCA"
Demo.dir_access()#无需例化,直接访问

输出结果

参数个数为 3
参数值为 Zara
参数值为 6
参数值为 F
参数个数为 4
参数值为 Mac
参数值为 36
参数值为 M
参数值为 MCA
YES!

block

如何定义block

  • 包含在{}内
  • 块名必须与调用这个块的函数名相同
block_name{
   statement1
   statement2
   ..........
}

如何调用block

  • 通过yield调用
  • 可以参数传递
#!/usr/bin/ruby
# -*- coding: UTF-8 -*-

def test
   yield 5,
   puts "在 test 方法内"
   yield 100
end
test {|i| puts "你在块 #{i} 内"}

运行结果

你在块 5 内
在 test 方法内
你在块 100
#!/usr/bin/ruby
# -*- coding: UTF-8 -*-

def test
   yield 5,6
   puts "在 test 方法内"
   yield 100,101
end
test {|i,j| puts "你在块 [#{i},#{j}] 内"}

运行结果

你在块 [5,6] 内
在 test 方法内
你在块 [100,101]

module

module是一种class, function, constant的集合,可以避免两个module内部子项的命名重复
问题。

  • module不能实例化
  • module没有子类
  • 引入module,用include modulename
  • module内的函数定义要modulename.
#!/usr/bin/ruby
module Week
   FIRST_DAY = "Sunday"
   def Week.weeks_in_month
      puts "You have four weeks in a month"
   end
   def Week.weeks_in_year
      puts "You have 52 weeks in a year"
   end
end

class Decade
include Week
   no_of_yrs=10
   DEMO = "Good"
   def no_of_months
      puts Week::FIRST_DAY
      number=10*12
      puts number
   end
   def print_demo
      puts DEMO
   end
end
d1=Decade.new
puts "---Access string in module:"
puts Week::FIRST_DAY
puts "---Call function in module:"
Week.weeks_in_month
puts "---Call function in module:"
Week.weeks_in_year
puts "---Call function in class:"
d1.no_of_months
puts "---Access constant in class:"
d1.print_demo

输出结果

---Access string in module:
Sunday
---Call function in module:
You have four weeks in a month
---Call function in module:
You have 52 weeks in a year
---Call function in class:
Sunday
120
---Access constant in class:
Good

同样也可以这么写,输出结果相同

#!/usr/bin/ruby
module Week
   FIRST_DAY = "Sunday"
   def weeks_in_month
      puts "You have four weeks in a month"
   end
   def weeks_in_year
      puts "You have 52 weeks in a year"
   end
end

class Decade
include Week
   no_of_yrs=10
   DEMO = "Good"
   def no_of_months
      puts Week::FIRST_DAY
      number=10*12
      puts number
   end
   def print_demo
      puts DEMO
   end
end
d1=Decade.new
puts "---Access string in module:"
puts Week::FIRST_DAY
puts "---Call function in module:"
d1.weeks_in_month
puts "---Call function in module:"
d1.weeks_in_year
puts "---Call function in class:"
d1.no_of_months
puts "---Access constant in class:"
d1.print_demo

module的mixins

ruby不支持多重继承,单是可以采用include多个module实现function的使用。

#!/usr/bin/ruby
# -*- coding: UTF-8 -*-

module A
   def a1
	  puts "A1"
   end
   def a2
	  puts "A2"
   end
end
module B
   def b1
	  puts "B1"
   end
   def b2
	  puts "B2"
   end
end
 
class Sample
include A
include B
   def s1
	  puts "S1"
   end
end
 
samp=Sample.new
samp.a1
samp.a2
samp.b1
samp.b2
samp.s1

迭代器

each迭代器

#!/usr/bin/ruby
 
ary = [1,2,3,4,5]
ary.each do |i|
   puts i
end

sum = 0
cutcome = {"block1" => 1000, "book2" => 1000, "book3" => 4000}
cutcome.each{|item, price| sum += price}
print "sum = " + sum.to_s

collect迭代器

#!/usr/bin/ruby
 
a = [1,2,3,4,5]
b = Array.new
b = a.collect{ |x| x*10 }
puts b

异常

raise抛出exception的多种形式

第一种

##!/tools/ruby/2.7.1/bin/ruby

THRESHOLD=4
class ExcpTest
    @@tmp_val=0
    def initialize
        begin
            if @@tmp_val<THRESHOLD
              puts "raise #{@@tmp_val+1} exception"
              raise 
            end
        rescue
            @@tmp_val+=1
            puts "enter rescue and retry,tmp_val=#@@tmp_val"
            retry
		ensure
			puts "always do print"
        end
    end

    def start
        puts "process start success"
    end
end

c1=ExcpTest.new
c1.start

输出结果

raise 1 exception
enter rescue and retry,tmp_val=1
raise 2 exception
enter rescue and retry,tmp_val=2
raise 3 exception
enter rescue and retry,tmp_val=3
raise 4 exception
enter rescue and retry,tmp_val=4
always do print
process start success

第二种

##!/tools/ruby/2.7.1/bin/ruby

THRESHOLD=4
class ExcpTest
    @@tmp_val=0
    def initialize
        begin
            if @@tmp_val<THRESHOLD
              raise "raise #{@@tmp_val+1} exception"
            end
        rescue Exception => e
            @@tmp_val+=1
			puts e.message
			puts e.backtrace.inspect
            puts "enter rescue and retry,tmp_val=#@@tmp_val"
            retry
        ensure 
			puts "always do print"
        end
    end

    def start
        puts "process start success"
    end
end

c1=ExcpTest.new
c1.start

输出结果

raise 1 exception
["script.rb:10:in `initialize'", "script.rb:26:in `new'", "script.rb:26:in `
'"]
enter rescue and retry,tmp_val=1
raise 2 exception
["script.rb:10:in `initialize'", "script.rb:26:in `new'", "script.rb:26:in `
'"]
enter rescue and retry,tmp_val=2
raise 3 exception
["script.rb:10:in `initialize'", "script.rb:26:in `new'", "script.rb:26:in `
'"]
enter rescue and retry,tmp_val=3
raise 4 exception
["script.rb:10:in `initialize'", "script.rb:26:in `new'", "script.rb:26:in `
'"]
enter rescue and retry,tmp_val=4
always do print
process start success

访问类中变量的三种方法

  • 构造器
  • 访问器
  • 设置器
#!/usr/bin/ruby

# 定义类
class Box
   # 构造器方法
   def initialize(w,h)
      @width, @height = w, h
   end

   # 访问器方法
   def getWidth
      @width
   end
   def getHeight
      @height
   end

   # 设置器方法
   def setWidth=value
      @width = value
   end
   # 构造器方法
   def setHeight(value)
      @height = value
   end
end

# 创建对象
box = Box.new(10, 20)

# 使用设置器方法
box.setWidth=30
# 使用构造器方法
box.setHeight(50)

# 使用访问器方法
x = box.getWidth()
y = box.getHeight()

puts "Width of the box is : #{x}"
puts "Height of the box is : #{y}"

类方法

类方法指在class中用self.functionname定义的函数,稚嫩个用Classname.functionname访问,不能用实例化的对象访问。

#!/usr/bin/ruby -w

class Box
   # 初始化类变量
   @@count = 0
   def initialize(w,h)
      # 给实例变量赋值
      @width, @height = w, h

      @@count += 1
   end

   def self.printCount()
      puts "Box count is : #@@count"
   end
   def to_s
	  "(w:#@width,h:#@height)"  # 对象的字符串格式
   end
end

# 创建两个对象
box1 = Box.new(10, 20)
# 调用类方法来输出盒子计数
Box.printCount()
box2 = Box.new(30, 100)

# 调用类方法来输出盒子计数
Box.printCount()
puts "String representation of box1 is : #{box1}"
puts "String representation of box2 is : #{box2}"

ruby常用标识符

$: = default search path (array of paths)
$! 最近一次的错误信息
$@ 错误产生的位置
$_ gets最近读的字符串
$. 解释器最近读的行数(line number)
$& 最近一次与正则表达式匹配的字符串
$~ 作为子表达式组的最近一次匹配
n 最近匹配的第 n 个子表达式 ( 和 n 最近匹配的第n个子表达式(和 n最近匹配的第n个子表达式(~[n]一样)
$= 是否区别大小写的标志
$/ 输入记录分隔符
$\ 输出记录分隔符
$0 Ruby脚本的文件名
$* 命令行参数
$$ 解释器进程ID
$? 最近一次执行的子进程退出状态

inspect

类中的运算符重载

#!/usr/bin/ruby -w

class Box
  attr_accessor :width, :height
  def initialize(width,height) # 初始化 width 和 height
    @width,@height = width, height
  end

  def +(other)         # 定义 + 来执行向量加法
	#puts "#{@width} #{other.w}"
    Box.new(@width + other.width, @height + other.height)
  end

  def -(other)         # 定义 - 来执行向量减法
    Box.new(@width - other.width, @height - other.height)
  end
 
  def -@               # 定义一元运算符 - 来对 width 和 height 求反
    Box.new(-@width, -@height)
  end
 
  def *(scalar)        # 执行标量乘法
    Box.new(@width*scalar, @height*scalar)
  end
  def to_s
    "(width:#@width,height:#@height)"  # 对象的字符串格式
  end
end

# 创建两个对象
box1 = Box.new(10, 20)
box2 = Box.new(30, 100)
box3 = box1.-@
puts "String representation of box3 is : #{box3}"
box4 = box1.*(2)
puts "String representation of box4 is : #{box4}"
box5 = box1+box2
puts "String representation of box5 is : #{box5}"

输出结果

String representation of box3 is : (width:-10,height:-20)
String representation of box4 is : (width:20,height:40)
String representation of box5 is : (width:40,height:120)

类中变量权限设定

  • attr_reader:不能在类外写
  • attr_writer:不能在类外读
  • attr_accessor:能在类外读写
#!/usr/bin/ruby -w

class Box
  attr_writer :length
  attr_reader :width
  attr_accessor :height
  def initialize(length,width,height) # 初始化 width 和 height
    @length,@width,@height = length, width, height
  end

  def to_s
    "(length:#@length,width:#@width,height:#@height)"  # 对象的字符串格式
  end
end

# 创建两个对象
box1 = Box.new(5, 10, 20)
puts "String representation of box1 is : #{box1}"
# attr_writer:length
box1.length = 10
a = box1.length
# attr_reader:width
box1.width = 20
b = box1.width
# attr_accessor:height
box1.height = 40
c = box1.height
puts "String representation of box1 is : #{box1}"

instance_eval

通过instance_eval实现代码块执行以更新obj实例。

#!/usr/bin/ruby -w

class MyClass
  def initialize
    @v = 1
  end
end
obj = MyClass.new
 
obj.instance_eval do
  puts self  #=> #<MyClass:0x33333 @v=1>
  @v = 3
  puts @v
end
 
v = 2
#obj.instance_eval { @v = v }
obj.instance_eval { puts @v }  # => 2

instance_eval &blk?

函数传参技巧

  • val:最基本
  • *val:一维不定长数组
  • **val:Hash型
  • &blk:将function传参
def my_map(a, &block)
   ary = []
   puts block.class
   a.each do |var|
      ary << block.call(var)
   end
   return ary
end

ar = ["hello", "world", "matz"]
puts my_map(ar, &:upcase)

输出结果

Proc
["HELLO", "WORLD", "MATZ"]

正则表达式

匹配word

  • (\w+) 匹配一次或多次?
  • (\w*) 匹配一次或多次?
  • ()具有优先级,举个例子,/(#(\w+))?.(\w+)=(\w+)/,则$1代表(#),$2代表第一个(\w+),$3$4依次往后。
arg = 'a#inst.warp_num = 1'
if(arg =~ /^(\w*)((#\w+)?\.(\w+)\s*=\s*\w+)/)
	puts $1 if $1
	puts $2 if $2
	puts $3 if $3
	puts $4 if $4
	puts 'c' unless $5
end

输出结果

a
#inst.warp_num = 1
#inst
warp_num
c

匹配空白字符

  • \s

Ruby进阶

高级函数传参

  • 逐层次传递执行块
  • 传递非定长输入
#!/usr/bin/ruby

class Type
    def initialize group,type
		@group = group
        @type = type
    end

    def grand *types
        types.each do |t|
			puts "#@group,#@type,#{t}"
        end
    end
end

class Group
    def initialize group
        @group = group
    end

    def type *types, &blk
        types.each do |t|
            tmp_type = Type.new(@group, t)
            tmp_type.instance_eval &blk if blk
        end
    end
end

$groups={}
def new_group grp,&blk
	tmp_grp = Group.new(grp)
    tmp_grp.instance_eval &blk
    $groups[grp] = tmp_grp
end

new_group "Vehicle" do
	type "Car","Ship" do
		grand "Benz"
	end
end

输出结果

Vehicle,Car,Benz
Vehicle,Ship,Benz

send实现调用其他class的function

class variable与class instance variable

class本身就是一个object

  • class variable @内部的直接def method无法访问
  • class instance variable 内部的def self.method 都可以访问
#!/usr/bin/ruby
# -*- coding: UTF-8 -*-
class Demo
	@class_var = 1
	@@class_inst_var = 2
	def print
		puts @class_var
		puts @@class_inst_var
	end
	def this.print
		puts @class_var
		puts @@class_inst_var
	end
end
Demo.new.print
Demo.print

class method与instance method

extend module: 类methd使用;
include module:只有实例化的才可以使用;
prepend module:如果已有instance method 会覆盖。

#!/usr/bin/ruby
# -*- coding: UTF-8 -*-
module SomeModule
	def print
		puts @val+3
	end
end
class Demo
	include SomeModule
	def initialize(val)
		@val = val
	end
	def Demo.print
		puts "own print"
	end
end
Demo.new(1).print
Demo.print

include是变为instance method,打印出 4 “own print”

#!/usr/bin/ruby
# -*- coding: UTF-8 -*-
module SomeModule
	def print
		puts @val+3
	end
end
class Demo
	extend SomeModule
	def initialize(val)
		@val = val
	end
	def print
		puts @val
	end
end
Demo.new(1).print
Demo.print

extend是变成class method

#!/usr/bin/ruby
# -*- coding: UTF-8 -*-
module SomeModule
	def print
		puts @val+3
	end
end
class Demo
	prepend SomeModule
	def initialize(val)
		@val = val
	end
	def print
		puts @val
	end
	def Demo.print
		puts "own print"
	end
end
Demo.new(1).print
Demo.print

prepend是将instance method覆盖

你可能感兴趣的:(ruby,学习,开发语言)