`
fireDragonpzy
  • 浏览: 442091 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

ruby base之类和对象

阅读更多
1、定义
若某个类被定义过,此时又用相同的类名进行定义,意味着对原有的类进行追加(重定义同一个类时,意味着对原有定义进行补充,不会覆盖原来的定义。而重定义方法时,则会覆盖原有定义。

2、变量
在ruby中,只有方法可以操作实例变量,因此可以说Ruby中的封装是强制性的。在对象外部不可以直接访问,只能通过接口方法访问。
class Person
  def name
    @name
  end
  def gender
    @gender
  end
  def age
    @age
  end
end

people = Person.new('Tom', 'male', 15)
puts people.name
puts people.gender
puts people.age

在Ruby中,一个对象的内部属性都是私有的。上面的代码中,我们定义了方法name,gender,age三个方法用来访问Person类实例对象的实例变量。注意name,gender,age访问只能读取相应实例变量,而不能改变它们的值。
我们也可以用成员变量只读控制符attr_reader来达到同样的效果。
class Person
  attr_reader :name, :gender, :age
end

类似地,我们可以定义方法去改变成员变量的值。
class Person
  def name=(name)
    @name=name
  end
  def gender=(gender)
    @gender=gender
  end
  def age=(age)
    @age=age
  end
end

people = Person.new('Tom', 'male', 15)
people.name = "Henry"
people.gender = "male"
people.age = 25

也可以用成员变量写控制符attr_writer来达到同样的效果。
class Person
  attr_writer :name, :gender, :age
end

我们也可以使用attr_accessor来说明成员变量既可以读,也可以写。
class Person
  attr_accessor :name, :gender, :age
end

也可以使用attr控制符来控制变量是否可读写。attr 只能带一个符号参数, 第二个参数是一个 bool参数,用于指示是否为符号参数产生写方法。它的默认值是 false,只产生读方法,不产生写方法。
class Person
  attr :name, true #读写
  attr :gender, true #读写
  attr :age, true #读写
  attr :id, false #只读
end

注意attr_reader,attr_writer,attr_accessor和attr不是语言的关键字,而是Module模块的方法。
class Test
  attr_accessor :value
end
puts Test.instance_methods - Test.superclass.public_methods
#执行结果为:
value
value=

上面代码中, 我们使用Test.instance_methods 得到Test 类所有的实例方法, 使用Test.superclass.public_methods得到Test父类所有的实例方法,然后相减就得到Test类不包含父类的所有的实例方法。
由于instance_methods方法返回值为一个Array,所以我们作差值运算
3、特殊方法与特殊类
特殊方法是指某实例所特有的方法。一个对象有哪些行为由对向所属的类决定,但是有时候,一些特殊的对象有和其他对象不一样的行为,在多数程序设计语言中,例如C++和Java,我们必须定义一个新类,但在Ruby中,我们可以定义只从属于某个特定对象的方法,这种方法我们成为特殊方法(Singleton Method)。
class SingletonTest
  def info
    puts "This is This is SingletonTest method"
  end
end
obj1 = SingletonTest.new
obj2 = SingletonTest.new
def obj2.info
  puts "This is obj2"
end
obj1.info
obj2.info
执行结果为:
This is This is SingletonTest method
This is obj2

有时候,我们需要给一个对象定义一系列的特殊方法,如果按照前面的方法,那么只能一个一个定义:
def obj2.singleton_method1
end
def obj2.singleton_method2
end

def obj2.singleton_method3
end
……
def obj2.singleton_methodn
end

这样做非常繁复麻烦,而且无法给出一个统一的概念模型,因此Ruby提供了另外一种方法,
class << obj
  ……
end

obj是一个具体的对象实例,class << 代表它的特殊类。
class SingletonTest
  def meth1
    puts "This is meth1"
  end
  def meth2
    puts "This is meth2"
  end
end

obj1 = SingletonTest.new
obj2 = SingletonTest.new

class << obj2
  def meth1
    puts "This is obj2's meth1"
  end
  def meth2
    puts "This is obj2's meth2"
  end
end
obj1.meth1
obj1.meth2
obj2.meth1
obj2.meth2
执行结果为:
This is meth1
This is meth2
This is obj2's meth1
This is obj2's meth2

4、类变量与类方法
1)类变量在使用前必须初始化,类变量在使用前必须初始化;类变量是私有的,在类外无法直接访问,你只能通过实例方法和类方法去访问它。
同样,类方法是属于一个类的方法,定义类方法时需要在方法前加上类名
2)Ruby和C++/Java的一个显著不同是存取控制是程序运行时决定的而不是静态绑定的。所以只有在访问一个受限制的方法时才会产生运行时错误。
3)方法的存取控制有三种:
  公有方法(Public Method)
      方法在任何地方都可以被调用,这是方法的默认存取控制。除了initialize和initialize_cpoy方法,他们永远是私有方法。
  保护方法(Protected Method)
      方法只能被定义这个方法的类自己的对象和这个类的子类的对象所访问。
  私有方法(private Method)
      方法只能被定义这个方法的类的对象自己访问,即使是这个类的其他对象也不能访问。
Ruby中的保护方法和私有方法与一般面向对象程序设计语言的概念有所区别,保护方法的意思是方法只能方法只能被定义这个方法的类自己的对象和子类的对象访问,私有方法只能被对象自己访问。
class Test
  def method1 #默认为公有方法
    …
  end
  protected #保护方法
  def method2
    …
  end
  private #私有方法
  def method3
  end
  public
  def test_protected(arg) #arg是Test类的对象
    arg.method2 #正确,可以访问同类其他对象的保护方法
  end
  def test_private(arg) #arg是Test类的对象
    arg.method3 #错误,不能访问同类其他对象的私有方法
  end
end

obj1 = Test.new
obj2 = Test.new
obj1.test_protected(obj2)
obj1.test_private(obj2)

也可以使用以下更简单的形式:
class Test
  def method1
    ...
  end
  def method2
    ...
  end
  def method3
    ...
  end
  def methdo4
    ...
  end
  public :method1
  protected :method2
  private :method3, :method4
end

Ruby和C++/Java的一个显著不同是存取控制是程序运行时决定的而不是静态绑定的。所以只有在访问一个受限制的方法时才会产生运行时错误。
5、元类
在Ruby中一切都是对象。类和实例对象都是对象。这句话听起来有点拗口,让我们来看一个例子:
class Person
  def initialize(name, gender, age)
    @name = name
    @gender = gender
    @age = age
  end
end
a = Person.new('Tom', 'male', 15)
puts a.object_id => 22429840
puts Person.object_id => 22429960

没错,类也是对象,这是Ruby和C++/Java的一个显著不同,在C++/Java中,类仅仅是一个数据抽象,并没有类也是对象这样的概念。而在Ruby中存在着元类的概念,类也是对象,所有类都是元类的实例对象。和C++/Java相比,Ruby的面向对象程度更高。
可以看到,类对象和实例对象一样有自己的ojbect_id,你可以象调用一个实例对象的方法一样去用它去调用类方法。所有类对象的类是Class类,Oject类是所有类的基类。
irb(main):003:0> Object.class
=> Class
irb(main):004:0> Object.superclass
=> BasicObject
irb(main):004:0> BasicObject.superclass
=> 

这样,我们可以从另一个角度去理解类变量与类方法,类变量就是一个类对象的实例变量,类方法就是指一个类对象类的特殊方法。
类方法具体可分为两种:第一种是在所有的类的父类Class中定义的,且被所有的类所共享的方法;第二种是各个类所特有的特殊方法。
类方法中的self指的是类本身,这点需要牢记,这样我们可以使用多种方式定义类方法。
class Test
  #定义类方法方式1
  def Test.meth1
    # ...
  end
  #定义类方法方式2
  def self.meth2
    # ...
  end

  #定义类方法方式3只能放在类定义里面
  class << Test
    def meth3
      # ...
    end
  end
  #定义类方法方式4
  class << self
    def meth4
      # ...
    end
  end
end

6、Ruby 的动态性
class UndefTest
  def meth
    puts "This is meth"
  end
end
obj1 = UndefTest.new
obj1.meth
class UndefTest
  undef_method(:meth)或者undef meth
end
obj1.meth
执行结果为:
This is meth
test.rb:14: undefined method `meth' for #<UndefTest:0x2ac8240> (NoMethodError)
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics