学习:ruby类
一、创建类:
class Car
#@@run_times是类变量,
@@run_times = 0
#类初始化,就如其他语言的构造函数
def initialize(_color)
#@color是实例变量, 实例变量用于在对象中保存对象
@color = _color
end
def set_color(_color)
@color=_color
end
#get_color是一个实例方法
def get_color
@color
end
# running 也是一个实例方法,就好比to_s方法
def running
@@run_times += 1
puts "一辆#{ get_color }车在跑..."
end
end
1、创建对象:
mycar = Car.new("red") // new调用了 initialize方法创建对象
puts mycar.get_color
mycar. running
2、ruby的属性:
可读属性:
attr_reader:color
可写属性:
atter_writer:color
可读写属性:(Car.new.color="b")
attr_accessor:color
3、实例变量
Ruby规定实例变量是以@开头,后跟一个名字。对实例变量的访问注意
a、在类内部可以对其赋值和读取没有限制
b、类外不能直接访问对象的实例变量,只能通过方法访问。正如上面所说的属性访问方式一样。
c、实例变量在使用前不用必须初始化。
4、类变量:类变量在类的所有对象中共享,也能被我们后面介绍的类方法访问。一个具体的类变量在给定的类中只有一个拷贝。
@@run_times 表示所定义过车的总数量。
Ruby规定类变量是以两个@@开头,后跟一个名字。对于一个给定的类而言,类变量只存在一份拷贝。
注意:
1)、类变量必须在使用之前要初始化。
2)、类变量是私有的。要想能从类外部访问,必须定义方法访问。这个方法是一个实例方法,要么是一个类方法。
3)、通常类变量属于包含该变量的最内层的类或模块。但是,可以为被定义该变量的类的所有子类所共享
5、 Ruby 的常量也是对对象的引用,常量通常在第一次被赋值的时候创建(通常是在类或模块中定义)。和其他语言不一样,
Ruby允许改变常量的值,因为常量是对对象的引用,通过改变常量的值,可以改变它所引用的对象的内部状态。
1)、在类或模块中的任何位置都可以直接访问该类或模块中定义的常量。
2)、在类或模块外,可以通过在域作用符::前加上一个返回适当类或模块对象的表达式来访问。
3)、对于不属于任何类或模块的常量,可以直接访问或使用不带前缀的域作用符来访问
4)、通过在常量名之前使用类或模块名和域作用符,还可以将常量从外面添加到已存在的类或模块中。
注意:
1)、类名本身就是常量。这就意味着可以把类和其他Ruby对象一样对待:可以拷贝它们;将它们作为参数传入方法;或者在表达式中使用它们
2)、如果一个无名的类赋值给了一个常量。Ruby将常量作为类名。
6、怎么样定义一个类的方法,就如java中提到的静态方法,用类名可以直接调用:
def Car.sum
end
要用类名.方法,也可以用self.方法
7、Ruby的self在不同的环境中有不同的含义,这点和java的this不同,原因是java实际上只有一种环境--在class的实例方法定义中使用,
代表访问这个方法参数自动传进的那个对象。而由于ruby作为一个完全纯净的面向对象语言,任何东东都是对象,方法是对象,类也是对象...,
所以self就会有很多环境,区分不同环境的self含义才能更好的理解程序的含义
二、继承类:
class Bmw < Car
def initialize(_color, speed)
super(color)
..
end
end
Bmw继承了父类的构造函数,使用super函数调用同时,get_color等方法也继承了。
1、super的使用:
1、在initialize中使用super,将调用其父类的initialize方法
2、在一般的实例方法中使用,将调用其父类中同名的方法。
向一个对象发送调用方法时,ruby的本质过程如下:
1、ruby将检查该对象所属的类,如果该类实现了该方法,就运行该方法
2、如果该类没有实现该方法,ruby将找到其直接父类中的方法,然后是其祖父类,凡此以往追溯整个祖先链
3、如果最终没有找到合适方法,ruby会产生一个特殊的行为,引发异常错误
2、重写方法,相当于覆盖:
class Bmw < Car
...
def running
@@run_times += 1
puts "一辆#{ get_color }车在飞奔..."
end
end
则会覆盖了父类Car的running方法
三、Ruby模块非常类似类, 除了:
> 模块不可以有实体
> 模块不可以有子类
> 模块由module...end定义.
1、一个模块对象也是Module的一个实例,这意味着所有的类都是模块。
2、模块有两种用法.其一是将相近的方法和实体放在一个相对集中的域里.
Ruby标准包里的Math模块就扮演着这一角色:
1.9.2-p320 :002 > Math.sqrt 4
=> 2.0
1.9.2-p320 :005 > Math::PI
=> 3.141592653589793
3、::操作符告诉 Ruby 解释器在哪里找常数的值(有可能其它模块用PI表示其它的一些东西).
如果我们想省掉 :: 直接调用一个模块的方法和常数,我们可以用 include:
1.9.2-p320 :006 > include Math
=> Object
1.9.2-p320 :007 > PI
=> 3.141592653589793
4、一些程序语言(如C++)提供了多重继承机制:一个类可以继承自多个超类。
例如,一个House可能继承自一个Building类(连同Office和Hospital类一起)。
尽管多重继承可能成为一种语言强有力的特征,
但是由于它会增加该语言的复杂性和歧义,因此许多面向对象语言都没有加入它。
(例如:java就没有多继承,但也可以用实现接口的方式来实现像多继承。)
Ruby支持单继承。然而,它还提供了mixin-它提供了多继承的许多特征。一个mixin是一种"模块"类型。
也就是模块的另一种用法。Ruby并未特意实现真正的多重继承,但糅和技术是一很好的替代.记得模块无法实体化或子类化;
但如果我们在类定义里include一个方法。