携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情
一、类变量与实例变量
与类方法和实例方法类似,类中的变量也有类变量和实例变量之分,类变量以 @@ 开头,在类对象层次共享,而实例变量以 @ 开头,仅作用与实例对象中,其他相同类的实例对象无法访问。
class Car
def initialize
# 创建实例对象时类变量数量加1,并且标记序号给实例变量
@@car_count = @@car_count + 1
@car_index = @@car_count
end
# 定义一个类变量
@@car_count = 0
# 类方法 返回 Car 类的实例数量
def self.car_count
@@car_count
end
# 返回实例对象的序号
def car_index
@car_index
end
# 实例方法返回 Car 类所有实例的数量
def car_count
@@car_count
end
end
# 实例化
c1 = Car.new
puts "现在有 #{c1.car_count} 个 Car 实例"
c2 = Car.new
puts "现在有 #{c2.car_count} 个 Car 实例"
puts "c1 的序号为 #{c1.car_index},共有 #{c1.car_count} 个 Car 实例"
puts "c2 的序号为 #{c2.car_index},共有 #{c2.car_count} 个 Car 实例"
执行上述代码,输出结果如下:
现在有 1 个 Car 实例
现在有 2 个 Car 实例
c1 的序号为 1,共有 2 个 Car 实例
c2 的序号为 2,共有 2 个 Car 实例
@@car_count 是类变量,是 c1 和 c2 共享的,@car_index 是实例变量, c1 和 c2 都有自己的实例变量,切不可访问对象的实例变量。
二、类的扩展与继承
类的扩展是动态语言的独有的特性,可以在不断的编码过程中多次定义类,来实现对类的方法和属性进行添加或者修改,如果扩展定义中的方法在原类中已经存在,新的方法则会覆盖旧的方法。
比如我们可以给 Ruby 的 Integer 类进行扩展。
class Integer
# 扩展新的方法
def sayIt
puts "我的值是 #{self }"
end
# 覆盖旧的方法
def abs
puts "abs 方法暂停使用"
end
# 扩展类方法
def Integer.sayHi
puts "Hi, I am Integer"
end
# 批量扩展类方法
class << Integer
def sayHelloAgain
puts "sayHelloAgain"
end
def sayHelloThird
puts "sayHelloThird"
end
end
end
# 实例化
8.sayIt
8.abs
Integer.sayHelloAgain
Integer.sayHelloThird
执行上述代码,输出结果如下
我的值是 8
abs 方法暂停使用
sayHelloAgain
sayHelloThird
继承则可以看做是另一种扩展类的方法,不过是创建一个新的类,然后在父类的基础上再进行扩展,Ruby 中的继承非常简单,只需要在定义类时使用 < 符号即可。
继承在 Ruby 中无处不在,定义类时,其实这个类已经包含了 Class 类的关系。在类方法中 self 关键字指的是类本身,在实例方法中值得是实例化对象, Python 中的 self 指的是实例化对象。
super 关键字用来引用父类的方法。
class Human
attr_accessor :name, :age
def say_hi
puts "Hi,我是 #{name}"
end
def say_age
puts "Hi, 我今年 #{age} 岁"
end
end
# 创建一个 Human 的子类 Man
class Man < Human
def gender
return "Male"
end
def say_gender
puts "Hi,I am #{self.gender}"
end
# 调用父类的方法
def say_hi
super
say_age
say_gender
end
end
# 实例化
m = Man.new
# 给父类中的属性赋值
m.name = "Tony"
m.age = 30
# 调用父类的方法
m.say_age
# 调用自己的方法
m.say_gender
# 子类中的方法和父类中的方法重名是,优先调用子类的方法
puts "=====开始调用子类和父类中重名的方法 say_hi====="
m.say_hi
执行上述代码,输出结果如下:
Hi, 我今年 30 岁
Hi,I am Male
=====开始调用子类和父类中重名的方法 say_hi=====
Hi,我是 Tony
Hi, 我今年 30 岁
Hi,I am Male
Man 类继承了 Human 类,所以 Man 类中就拥有了 Human 类的属性和方法,可以直接修改属性和调用方法,当父类和子类中有重名的方法时,优先调用子类的方法,并且在方法中可以通过 super 关键字来调用父类的方法。
三、别名
别名可以创建一个新的名字作为对已有的方法、操作符或者全局变量的引用,别名是通过 alias 关键字来定义的
alias 新名字 旧名字
alias 中的名字参数可以是合法的字符也可以师傅好,当为方法起别名时,新的名字将指向原有方法的一个备份,也就是如果后来旧的方法被覆盖重新定义,别名依然后调用就得代码,这一功能常用于实现多态。
class Integer
# 创建一个 plus 方法的别名
alias plus +
def +(val)
return self.plus(val*2)
end
end
puts 2 + 1 # 4
puts 2.plus(1) # 3