一、Ruby 的类
在前面的文章中提到对象的创建,虽然我们可以使用 Object.new 来常见一个对象,并给对象定义各种行为或者方法,但是如果对象的方法较多,显然一个一个的定义是不合适的,那么如何才能让对象创建之处就拥有了一定的行为和方法呢?
Ruby 中的类可以很方便的把一组行为或者方法打包,以便快速的创建在本质上行为一致的对象。
Ruby 中处理每一件事,要么是一个对象,要么是一个生成对象的构造过程,而每一个对象都是某些类的实例。类是用于组织对象和方法的一种方式。
一个典型的类包含了一系列方法定义的集合,通常类存在的目的是为了被实例化。Ruby 中使用 class
关键字定义一个类。类使用常量命名,通常首字母大写,常量是用于存储信息和值,其值在实例化过程中或者程序运行过程中不可更改。
接下来我们定义一个 Ticket 类,并在 Ticket 可内部定义一个 info 方法。
class Ticket def info puts "Iron Man4" end end 复制代码
然后我们可以创建一个 Ticket 对象
t1 = Ticket.new t1.info 复制代码
执行上述代码,输出结果如下:
Iron Man4 复制代码
与之前创建的对象相比,Ticket 实例化的对象一开始就拥有 info 方法,而不是在对象创建之后定义的。
二、实例方法
我们将 Ticket 类内部定义的 info 方法称为实例方法,info 方法将被所有的 Ticket 类的实例化对象共享。
plus:在对象创建之后再定义行为,如 def obj.say_hi
这种方式定义的方法称之为单例方法,只有当前这个对象可以调用,其他对象无法调用。
一旦类中定义好了实例方法,就不能再次定义同名的实例方法了,否则原先定义的实例方法会被覆盖。
class Cat def name puts "皮皮" end def name puts "猪猪" end end c1 = Cat.new c1.name 复制代码
执行上述代码,输出内容如下:
猪猪 复制代码
根据输出内容可以确定,第二个 name 实例方法覆盖了第一个 name 实例方法。
重开类
在定义一个类时,就创建了单个类定义的代码块,但是再定义一个同名的类进行一些内容的添加或者修改在 Ruby 中也是可行的。
class Movie def price puts "39.9" end end class Movie def name puts "Iron Man" end end m = Movie.new m.price m.name 复制代码
执行上述代码,输出结果如下:
39.9 Iron Man 复制代码
上述代码中,通过两次定义 Movie 类,分别添加了两个方法,当然你也可以把方法放在同一个类中,这样会使代码更容易阅读。
把类分开定义的原因是使用了多个文件扩展类。
三、实例变量
在之前的创建对象实例中,我们定义 Movie 对象的 name 或者 price 都是通过方法来已定义的,这也就导致了我们创建的每一个 Movie 对象的 name 或者 price 都是相同的,我们需要通过一种方式来创建出不同的 Movie 对象,替换这种硬编码的方式。
对象管理的信息或者存储的数据体现了对象的状态,对象可以设置或者重置状态。
Ruby 对象中提供了可以方便进行数据存储和提取的机制,即实例变量。实例变量的使用和其他变量非常类似,先赋值,然后使用,可以进行一系列的操作。
- 实例变量的命名要以
@
符号开头 - 实例变量仅仅在所属的对象内部可见
- 一个实例变量在类的其中一个方法中初始化,然后可以在这个类的任何地方使用
class Tesla def set_name(name) puts "Set Tesla name" @name = name end def get_name puts "Get Tesla name" @name end end roadster = Tesla.new roadster.set_name("Roadster II") puts roadster.get_name 复制代码
执行上述方法,输出内容如下:
Set Tesla name Get Tesla name Roadster II 复制代码
@name 实例变量会保存赋予的值并在方法调用期间“存活”,适用于对象状态的保存。
使用状态初始化对象
我们也可以给对象设置一个默认的状态,即对象一旦创建就自动拥有某种状态。我们可以定义一个 initialize 方法,通过该方法设置对象的默认状态。
class Tesla def initialize(name,price) @name = name @price = price end def get_name @name end def get_price @price end end 复制代码
上述方法中定义了 initialize 方法需要两个参数,分别是 name 和 price,在实例化时就需要提供这两个值
t1 = Tesla.new("model3", "260000") puts t1.get_name t2 = Tesla.new("modely", "290000") puts t2.get_name 复制代码
执行上述代码,输出结果如下:
model3 modely 复制代码
这就实现了在对象创建时就定义对象的状态,并且在对象的生命周期中获取这些值。