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