1.
class ColoredRectangle
def initialize(r, g, b, s1, s2)
@r, @g, @b, @s1, @s2 = r, g, b, s1, s2
end
def ColoredRectangle.white_rect(s1, s2)
new(0xff, 0xff, 0xff, s1, s2)
end
def ColoredRectangle.gray_rect(s1, s2)
new(0x88, 0x88, 0x88, s1, s2)
end
def ColoredRectangle.colored_square(r, g, b, s)
new(r, g, b, s, s)
end
def ColoredRectangle.red_square(s)
new(0xff, 0, 0, s, s)
end
def inspect
"#@r #@g #@b #@s1 #@s2"
end
end
a = ColoredRectangle.new(0x88, 0xaa, 0xff, 20, 30)
b = ColoredRectangle.white_rect(15,25)
c = ColoredRectangle.red_square(40)
2.。
class PersonalComputer
attr_accessor :manufacturer,
:model, :processor, :clock,
:ram, :disk, :monitor,
:colors, :vres, :hres, :net
def initialize(&block)
instance_eval &block
end
# Other methods...
end
desktop = PersonalComputer.new do
self.manufacturer = "Acme"
self.model = "THX-1138"
self.processor = "986"
self.clock = 9.6 # GHz
self.ram = 16 # Gb
self.disk = 20 # Tb
self.monitor = 25 # inches
self.colors = 16777216
self.vres = 1280
self.hres = 1600
self.net = "T3"
end
p desktop
这边主要是使用了一个instance_eval方法,它和eval很像,只不过他是在一个给定的对象的上下文中对一个字符串,或者一个block进行求值.这里还要注意的是block中的self
是必须的.如果你想要将一个属性的存取方法去除掉,你可以在block的结尾加上undef(后面是你的方法名):
desktop = PersonalComputer.new do
self.manufacturer = "Acme"
self.model = "THX-1138"
undef model
end
p desktop.model #报错
创建一个实例属性
这个很简单,有好几种方法:
class Person
def name
@name
end
def name=(x)
@name = x
end
def age
@age
end
end
class Person
attr :name, true # Create @name, name, name=
attr :age # Create @age, age
end
class SoundPlayer
MAX_SAMPLE = 192
def SoundPlayer.detect_hardware
# ...
end
def play
# ...
end
end
class SomeClass
attr_reader :a1, :a2 # Creates @a1, a1, @a2, a2
attr_writer :b1, :b2 # Creates @b1, b1=, @b2, b2=
attr_accessor :c1, :c2 # Creates @c1, c1, c1=, @c2, c2, c2=
# ...
end
最常用第三种.
3创建一个类级别的属性和方法.
一个方法或者属性不只能关联到一个实例,而且还能关联到类它自己:
创建一个类方法:
class SoundPlayer
MAX_SAMPLE = 192
def play
# ...
end
end
def SoundPlayer.detect_hardware
# ...
end
两种的区别是,当类方法被定义在类的外面时,他的常量不在它的作用域中,也就是说在第二种方法里面要得到常量MAX_SAMPLE,必须这样,SoundPlayer::MAX_SAMPLE .
类变量的话是以@@开头,看下面的例子:
class Metal
@@current_temp = 70
attr_accessor :atomic_number
def Metal.current_temp=(x)
@@current_temp = x
end
def Metal.current_temp
@@current_temp
end
def liquid?
@@current_temp >= @melting
end
def initialize(atnum, melt)
@atomic_number = atnum
@melting = melt
end
end
aluminum = Metal.new(13, 1236)
copper = Metal.new(29, 1982)
gold = Metal.new(79, 1948)
Metal.current_temp = 1600
puts aluminum.liquid? # true
puts copper.liquid? # false
puts gold.liquid? # false
Metal.current_temp = 2100
puts aluminum.liquid? # true
puts copper.liquid? # true
puts gold.liquid? # true
这里的类变量在类方法被调用之前就被实例化了。要注意的是,我们能够从一个实例方法里面存取一个类变量,但是我们不能从一个类方法存取一个实例变量.
class Test
def Test.test
puts @a
end
def tests
puts @a
end
def a=(x)
@a=x
end
end
temp=Test.new
temp.a="2"
Test.test #nil
temp.tests #2
当我们想要从一个类方法中打印出一个实例变量会出现什么呢,这时就会打印出nil.为什么是这样呢?原因是这时我们打印出的已经不是这个类的实例变量了,而是Class类的一个实例变量,因此会打印出nil.
还有一种叫做是类实例变量,这边只是简要的介绍,后面我们会详细的介绍:
class MyClass
SOME_CONST = "alpha" # A class-level constant
@@var = "beta" # A class variable
@var = "gamma" # A class instance variable
def initialize
@var = "delta" # An instance variable
end
def mymethod
puts SOME_CONST # (the class constant)
puts @@var # (the class variable)
puts @var # (the instance variable)
end
def MyClass.classmeth1
puts SOME_CONST # (the class constant)
puts @@var # (the class variable)
puts @var # (the class instance variable)
end
end
def MyClass.classmeth2
puts MyClass::SOME_CONST # (the class constant)
# puts @@var # error out of scope
puts @var # (the class instance variable)
end
myobj = MyClass.new
MyClass.classmeth1 # alpha, beta, gamma
MyClass.classmeth2 # alpha, gamma
myobj.mymethod # alpha, beta, delta
可见这边是建立了两个变量(虽然名字什么都是一样),一个是类实例变量,一个是实例变量,当在类方法中使用的是类实例变量,而在实例方法中调用的是实例变量.
4 测试一个对象所属的类
经常我们需要知道这个对象是属于那个类的,这里有很多方法:
class 方法将会返回一个对象的类,和它同义的方法type 已经被废弃了:
s = "Hello"
n = 237
sc = s.class # String
nc = n.class # Fixnum
不要被class方法所返回的东西所迷惑,其实它返回的是一个Class类的实例,因此我们能够调用返回类型的类方法,看起来就好像是Class的一个实例方法:
s2 = "some string"
var = s2.class # String
my_str = var.new("Hi...") # A new string
我们能够比较一个变量和一个类名来看他们是否相等,甚至我们能够使用一个变量作为一个超类,从而定义一个子类.这里只要记住在ruby中,Class是一个对象,Object是一个类.
我们如果想要知道一个变量是否属于某一个类,我们能这样做:
puts (5.instance_of? Fixnum) # true
puts ("XYZZY".instance_of? Fixnum) # false
puts ("PLUGH".instance_of? String) # true
如果我们想要测试一个有继承关系的对象时,我们可以使用kind_of?或者is_a?方法:
n = 9876543210
flag1 = n.instance_of? Bignum # true
flag2 = n.kind_of? Bignum # true
flag3 = n.is_a? Bignum # true
flag3 = n.is_a? Integer # true
flag4 = n.is_a? Numeric # true
flag5 = n.is_a? Object # true
flag6 = n.is_a? String # false
flag7 = n.is_a? Array # false
控制方法的存取
定义一个private方法:
class Bank
def open_safe
# ...
end
def close_safe
# ...
end
private :open_safe, :close_safe
def make_withdrawal(amount)
if access_allowed
open_safe
get_cash(amount)
close_safe
end
end
# make the rest private
private
def get_cash
# ...
end
def access_allowed
# ...
end
end