therubyway:ruby way的OOP的 2

  1 理解allocate

  在些特殊环境中你可能需要不构造器(也就是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 




Tags:  ruby安装 ruby是什么意思 rubyonrails therubyway

延伸阅读

最新评论

发表评论