ruby way之OOP之一

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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值