在些特殊环境中你可能需要不它构造器(也就是initialize)来创建个对象也就是说你想要创建个空对象.例如假设你有个对象它状态完全由它存取思路方法所确定因此如果你不是真想要个另外状态话思路方法是没必要.此时我们能allocate思路方法.
Ruby代码
Person
attr_accessor :name, :age, :phone
def initialize(n,a,p)
@name, @age, @phone = n, a, p
end
def test
p "aaa"
end
end
p1 = Person.("John Smith",29,"555-1234")
p2 = Person.allocate
p p1.age # 29
p p2.age # nil
p2.test
2 Modules
在ruby中使用Modules有两个原因.第个原因是 管理,当我们在module中存储常量和思路方法时我们将会有更少命名冲突.module中思路方法和类思路方法很类似就是模块名+思路方法名.因此我们看到File.ctime 和FileTest.exist?, 时我们从表面无法知道 File和FileTest是模块还是类.
第 2个原因更有趣我们能使用模块进行mixin.有关什么是mixin就不说了
个模块也能有例子思路方法当某个类了它的后这些例子思路方法就变成那个类了
Ruby代码
module MyMod
def meth1
puts "This is method 1"
end
end
MyClass
MyMod
# ...
end
x = MyClass.
x.meth1 # This is method 1
但是如果有个模块思路方法时要如何办你可能认为他们被作为类思路方法来但是ruby没有这种行为module methods 没有被mixed in
可是我们如果想要这样使用我们有个小窍门技巧.我们可以覆盖个叫做append_features思路方法来实现模块思路方法mix.看下面例子:
Ruby代码
module MyMod
def MyMod.append_features(someClass)
def someClass.modmeth
puts "Module () method"
end
super # This call is necessary!
end
def meth1
puts "Method 1"
end
end
MyClass
MyMod
def MyClass.meth
puts "Class method"
end
def meth2
puts "Method 2"
end
end
x = MyClass.
# Output:
MyClass.meth # Class method
x.meth1 # Method 1
MyClass.modmeth # Module () method
x.meth2 # Method 2
这是个非常有价值例子.首先我们应当理解append_features 不是个当发生时就被hook它实际上做是 操作工作.这就是为什么super思路方法在这里是必须了没有super模块剩下(这里是meth1 )将不会被.
这里还要注意是append_features里面定义了个思路方法在ruby中思路方法内部定义思路方法只能是singleton method (也就是说要么是类思路方法要么是模块思路方法).如果你尝试着定义个例子思路方法就会抛出个Nested method error.
有时个模块可能想要决定个mixin发起类append_features 也可以做这个它参数就是那个类.
我们其实也可以mix个例子思路方法作为类思路方法:
Ruby代码
module MyMod
def meth3
puts "Module instance method meth3"
puts "can become a method."
end
end
MyClass
<< self # Here, self is MyClass
MyMod
end
end
MyClass.meth3
# Output:
# Module instance method meth3
# can become a method.
如果我们使用extend代码就变成这样了:
Ruby代码
MyClass
extend MyMod
end
我们这里谈论都是思路方法那么例子变量呢它能被mix吗尽管模块拥有自己例子数据是可能可是经常都不需要这样做.
mix个模块到个对象也是可以操作后面我们会介绍.
我们可以mix Comparable模块 和定义<=> 思路方法这样话我们就能使用<, >, <=, 这样操作.
3 转换个对象
这张其实前面几张都有了比如to_s和to_str区别比如coerce使用因此这边就简要介绍下了.
看下面例子
Ruby代码
String
def coerce(n)
self['.']
[n, Float(self)]
[n, Integer(self)]
end
end
end
x = 1 + "23" # 24
y = 23 * "1.23" # 29.29
也就是说*或者+时候会将串转换而数字将不会做任何动作.
4 创建个只有数据类(Structs)
可能你想这样做:
Ruby代码
Address
attr_accessor :street, :city, :state
def initialize(street1, city, state)
@street, @city, @state = street, city, state
end
end
books = Address.("411 Elm St", "Dallas", "TX")
虽然这样也可以做可是他太丑陋了在ruby中我们有Struct 来做这个事.我们能够这样使用Struct:
Ruby代码
Address = Struct.("Address", :street, :city, :state)
books = Address.("411 Elm St", "Dallas", "TX")
那么思路方法第个参数意思是什么呢?当我们Struct.创建个新structure template 时个新类就通过Struct 类他自己被创建这个类名字就是第个参数内容因此我们还能这样做:
Ruby代码
Struct.("Address", :street, :city, :state)
books = Struct::Address.("411 Elm St", "Dallas", "TX")
当你创建个structure 例子时候不定要把所有变量都写上当你时忽略变量它会默认为nil
这里话不要创建个名叫TmsStructStruct内置了个Tms类
5 冻结对象
我们如果想要保护个对象不被改变这时我们能使用freeze 思路方法
Ruby代码
str = "This is a test. "
str.freeze
begin
str << " Don't be alarmed." # Attempting to mody
rescue => err
puts "#{err.} #{err}"
end
arr = [1, 2, 3]
arr.freeze
begin
arr << 4 # Attempting to mody
rescue => err
puts "#{err.} #{err}"
end
# Output:
# TypeError: can't mody frozen
# TypeError: can't mody frozen .gif' />
但是这里注意是freeze 操作是对象引用而不是那个变量请看下面例子:
Ruby代码
str = "counter-"
str.freeze
str "uitive" # "counter-uitive"
arr = [8, 6, 7]
arr.freeze
arr [5, 3, 0, 9] # [8, 6, 7, 5, 3, 0, 9]
这里可以看到str使用的后创建了个新对象这时str指向了新对象因此新对象并没有被冻结而老对象依旧被冻结了
frozen? 思路方法返回个对象是否被冻结.
Ruby代码
hash = { 1 => 1, 2 => 4, 3 => 9 }
hash.freeze
arr = hash.to_a
puts hash.frozen? # true
puts arr.frozen? # false
hash2 = hash
puts hash2.frozen? # true
最新评论