Class类

#所有类都是Class类的实例化对象
String.class #Class
Object.class #Class

#Class类也是Class类的实例化对象
Class.class #Class

1.类定义和当前类

#1.在类定义中,当前对象self就是正在定义的类,当前类就是self就是正在定义的类。
#2.如果有一个类的引用,则可以用class_eval()方法打开这个类。
def add_method_to(a_class)
  a_class.class_eval do
  #class_eval的别名是module_eval
    def m
      puts "hello"
    end
  end
end

add_method_to String
"abc".m  #=>"hello"

#3.方法中定义方法
class MyClass
  def method_one
    def method_two
      puts "hello"
    end
  end
end

obj = MyClass.new
obj.method_one #调用method_one,定义method_two
obj.method_two

2.类实例变量

#1.所有的实例变量属于当前self,属于当前类的实例变量是类实例变量
#2.类实例变量只能被类本身通过函数方法访问,而不能被类的实例或者子类所访问

class MyClass
  @my_var = 1

  def self.read
    @my_var
  end

  def write
    @my_var = 2
  end

  def read
    @my_var
  end
end

obj = MyClass.new
obj.write
puts obj.read #>2
puts MyClass.read #>1

#不能通过这个类或者类的对象直接调用这个变量
MyClass.my_var  #=>undefined method my_var
#而是通过调用方法的形式调用这些变量,代码如下所示:
obj.read #>2
MyClass.read #>1

3.类变量

1.和类实例变量不同,类变量可以被子类或者类的实例通过方法访问
2.类变量不属于真正的类,他们属于类体系结构(不理解)

class MyClass
  @@my = 1

  def self.read
    @@my_var
  end

  def write
    @@my_var = 2
  end

  def read
    @@my_var
  end
end

class SonClass < MyClass
end

son_obj = SonClass.new
son_obj.read  #=>1
obj = MyClass.new
obj.write
obj.read #=>2
MyClass.read #=>2

#下面的代码说明类变量不属于真正的类,他们属于类体系结构。
@@v = 1
class MyClass
  @@v = 2
end

puts @@v #=>2  
#warning class variable access from toplevel
# @@v定义于main的上下文,它属于main的类Object,所以也属于Object的所有后代

4.使用Class定义类

#定义一个Array的子类:
class MyClass < Array
  def my_method
    puts "hello"
  end
end

#不使用class关键词定义Array的子类:
c = Class.new(Array) do
  def my_method
    puts "hello"
  end
end

MyClass = c
puts c.name  #=>MyClass

#类是匿名类,类名其实是常量,如下的形式给类进行赋值:
MyClass = c
#从最后一句可以知道c.name是这个类的名字。

#其实直接给类进行常量赋值也是可以的,见如下的代码:
MyClass = Class.new(Array) do
  def my_method
    puts "hello"
  end
end

obj = MyClass.new
obj.my_method

5.单件方法

#1.针对单个对象生效的方法叫做单件方法
#2.类方法也是单件方法,类也是对象,方法叫做类方法

#如下代码是字符串对象生成单件方法:
str = "just a regular string"

def str.title? #定义对象的单件方法
  self.upcase ==self
end

#定义类的单件方法,也被称为类方法
class MyClass
  def MyClass.method_one
    puts "this is the method_one"
  end

  def self.method_two
    puts "this is the method_two"
  end

  class << self
    def method_three
      puts "this is the method_three"
    end
  end
end

6.类宏

#1.attr_accessor()这样的方法被成为类宏,是普通的方法,可以用在类定义中。

#类宏的真实形式
class MyClass
  def my_attribute=(value)
   @my_attribute = value
  end

  def my_attribute
    @my_attribute
  end
end

obj = MyClass.new
obj.my_attribute = "x"
puts obj.my_attribute #=>"x"

#上面的代码的简化形式
class MyClass
  #这是类宏的表示形式
  attr_accessor :my_attribute
  #定义两个方法和一个实例变量
end

obj = MyClass.new
obj.my_attribute = "x"
puts obj.my_attribute  #=>"x"

#类宏进行应用
class Book
  def title
    puts "this is the title"
  end

  def self.deprecate(old_method, new_method)
    define_method(old_method) do |*args, &block|
      warn "Warning :#{old_method}() is deprecated, use #{new_method}()"
      send(new_method, *args, &block)
    end
  end

  deprecate :GetTitle, :title #调用和定义方法
end

book = Book.new
book.GetTitle  #=>结果为预期所示

8.类属性

#1.对象属性就是通过对象调用方法来达到访问属性的目的
#2.类属性就是直接通过类名直接调用属性的方式
#代码示例,对象属性
class MyClass
  attr_accessor :a
end
obj = MyClass.new
obj.a = 2
abj.a  #=>2

#代码示例,类属性
class Class
  attr_accessor :b
end
class MyClass
end
MyClass.b = 42
MyClass.b #=> 42

#总结
1.类MyClass是类Class的对象,因此类MyClass可以直接调用类Class的实例方法,
2.如果是专属于MyClass的属性,需要另外一种技术,是添加类方法的另外一种形式:

#通过实例代码打开eigenclass表示类属性
class MyClass
  #打开eigenclass域,定义类方法,通过类宏的形式,可以获得类的属性
  class << self
    attr_accessor :c
  end
end
MyClass.c = "this is class singleton attribute"
MyClass.c #=>"this is class singleton attribute"

9.类扩展和对象扩展

#1.类中include一个具有模块方法的模块,该方法是该类的类方法,也是该类单件类的实例方法,这种技术叫类扩展。
#2.将上面的类扩展应用到任意对象上,叫做对象扩展。

#当类包含模块时,获得的是该模块的实例方法,而不是类方法
#而模块中的类方法存在于模块的eigenclass中,无法触碰。
module MyModule
  def self.my_method
    puts "hello"
  end
end

class MyClass
  include MyModule
end

MyClass.my_method  #NoMethodError!

#将模块引入到类的eigenclass中,这样子类就可以将模块中的实例方法作为类方法引入:
module MyModule
  def my_method
    puts "hello"
  end
end

class MyClass
  class << self
    include MyModule
  end
end

MyClass.my_method  #=>hello

#上面的技术是类扩展,应用到任意对象上是对象扩展
module MyModule
  def my_method
    puts "hello"
  end
end

obj = Object.new
class << obj
    include MyModule
end

obj.my_method  #=>hello
obj.singleton_methods #=>[:my_method]
#使用Object#extend方法也可以实现类扩展和对象扩展
module MyModule
  def my_method
    puts "hello"
  end
end

obj = Object.new
obj.extend MyModule
obj.my_method  #=>hello

class MyClass
  #是self.extend的省略形式
  extend MyModule #实例对象和类对象都可以直接调用extend方法,解释如下
end
MyClass.my_method #=>hello

#extend是Object类的方法,所以对象obj可以调用该方法
#MyClass可以直接调用extend方法,MyClass是Class类的对象,而Class类的祖先链包括Object,在类中可以直接使用该类的类方法:

#module中执行模块方法(比如执行attr_accessor),这个module被extend之后会成为对象属性
module One
  attr_accessor :name
end

class Demo
end

obj = Demo.new
obj.extend One
obj.name = "jayzen"
p obj.name

results matching ""

    No results matching ""