2.5.5 符号
符号是Ruby内置类Symbol的实例。它有一个字面构造器:冒号引导符。可以通过这个记号,从字面航辨认出符号与字符串、变量名、方法名或者其他的区别。
符号的特点:
- 不变性。符号是不可变的。符号不能添加字符,一旦它存在,就不能修改
- 唯一性。符号是唯一的。无论何时看到:abc,看到的都是同一个对象
实践
符号最常用的用法:方法参数和散列键:
#方法参数
puts "abc".send(:upcase) #等价于puts "abc".send(upcase.to_sym)
#输出结果:ABC
#--------------------
#散列键
d_hash = {:name => "zhangsan", :age => 25}
puts d_hash[:age]
#输出结果:25
使用符号的好处:
1.Ruby处理符号更快,因此如果要大量处理散列的查找,就会节省一些时间。如果需要性能上的优化,使用符号作为散列键则可能是个好办法。
2.Ruby允许一种特殊的符号表现形式在散列键的位置出现,它可以在符号之后使用冒号,同事可以替代散列的分割箭头符,例如:
d_hash = {name: "zhangsan",age: 23}
#等价于
d_hash = {"name" => "zhangsan","age" => 23}
2.6 类和对象
2.6.1 创建类
class Student
attr_accessor :s_name,:s_age, :s_class
def initialize(name,age,t_class)
@s_name = name
@s_age = age
@s_class = t_class
end
def study
puts "study"
end
end
s1 = Student.new("zhangsan",15,"1年级")
p s1.s_name
s1.study
2.6.2 类的继承
Ruby语言遵从单继承原则,无法继承多个类,也就意味着它只是一个超类。
class Student < People
end
2.6.3 给类添加属性
原始添加方法:
class Ticket
def initialize(ve,date)
@venue = ve
@date = date
end
def price=(pr)
@price = pr
end
def venue
@venue
end
def date
@date
end
def price
@price
end
end
attr_reader & attr_writer
class Ticket
attr_reader :venue, :date, :price #读取方法
attr_writer :venue, :date, :price #写方法
def initialize(ve,date)
@venue = ve
@date = date
end
end
ti = Ticket.new("北京大学","2019-09-01")
ti.venue = "sdfsdfd"
puts ti.venue
attr_accessor
class Ticket
attr_accessor :price,:venue,:date
def initialize(ve,date)
@venue = ve
@date = date
end
end
ti = Ticket.new("北京大学","2019-09-01")
ti.price = 200
puts ti.price
区别于attr,attr: price只生成了reader,attr: price,true会生成getter和setter。
2.7 模块
Ruby鼓励读者进行模块化设计:将大的组件分解为小的,并可以混合(mixin)和匹配对象的行为。和类一样,模块是一组方法和常量的集合。
模块是使用混合到类的方式。
模块没有实例
创建模块使用module关键字:
module Category
def say_hello
puts "Category's Hello"
end
end
class Student
include Category #引用模块
def initialize
end
end
st = Student.new
st.say_hello
2.7.1 include vs prepend
module ModuleGoOne
def go
puts "ModuleGoOne's go"
end
end
module ModuleGoTwo
def go
puts "ModuleGoTwo's go"
end
end
class Student < Person
include ModuleGoOne
prepend ModuleGoTwo
def go
puts "Student's go"
end
end
st = Student.new
st.goto
# Result is ModuleGoTwo's go
方法查找规则
module ModuleGoOne
def go
puts "ModuleGoOne's go"
end
end
module ModuleGoTwo
def go
puts "ModuleGoTwo's go"
end
end
class Person
def go
puts "Person's go"
end
end
class Student < Person
include ModuleGoOne
prepend ModuleGoTwo
def go
puts "Student's go"
end
end
st = Student.new
st.go
方法查找规则:
1.先查找当前类中是否有该方法,如果有,则直接调用,执行完毕;
2.查找module中是否有该方法,如果有,则调用,执行完毕;
3.查找父类中是否有该方法,父类中是否有module,如果有prepend模块,则先调用,没有的话如果有在类中定义,则调用;
4.所属的超类
5.内置Kernel模块
6.BasicObject
7.method_missing NoMethodError
2.8 Ruby块yield
块由大量代码组成。
块中的代码总是包含在大括号内
块的调用:需要与其相同名称的方法调用
可以使用yield语句来调用块
每个Ruby源文件可以声明当文件被加载时要运行的代码块(BEGIN),以及程序完成执行后要运行的代码块(END)。
BEGIN {
puts "BEGIN..."
}
END {
puts "END......."
}
def test
yield
end
test {puts "Hello"}
=begin
def t