`
Hooopo
  • 浏览: 335120 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

alias迷思

    博客分类:
  • Ruby
阅读更多
对alias还不太熟悉,看到下面的代码有点晕了..
class Adaptee
  def talk; puts 'Adaptee';end
end
class Adapter < Adaptee
  alias talkee talk
  def talk
	puts 'before Adaptee'
	talkee
	puts 'after Adaptee'
  end
end
Adapter.new.talk



迷惑1:alias talkee talk是把Adapter#talk还是Adaptee#talk拷贝一份并起个新名字talkee呢?
迷惑2:alias talkee talk的位置,放在下面会如何呢?
迷惑3:怎么感觉这个程序会无限递归呢(实际没有..)

都说*nix下有事找男人(man),学ruby有事没事日(ri)一下...
---------------------------------------------------- Module#alias_method
     alias_method(new_name, old_name)   => self
------------------------------------------------------------------------
     Makes _new_name_ a new copy of the method _old_name_. This can be
     used to retain access to methods that are overridden.

        module Mod
          alias_method :orig_exit, :exit
          def exit(code=0)
            puts "Exiting with code #{code}"
            orig_exit(code)
          end
        end
        include Mod
        exit(99)

     _produces:_

        Exiting with code 99


这个例子更让人迷惑..本来有继承关系的时候就迷糊了,现在这个例子又多出来一个exit(Kernel下定义的方法)

于是只好自己简化一些:

module TestAlias
 alias _say say
 def say
   puts "Hello"
 end
end
include TestAlias
_say
#undefined method `say' for module `TestAlias' (NameError)

module TestAlias
 def say
   puts "Hello"
 end
 alias _say say
end
include TestAlias
_say
#hello

结论1:alias和位置有关要alias的方法必须之前有定义..
继续折腾:
def say
  puts "From Top Level"
end
module TestAlias
 alias _say say
 def say
   puts "Hello"
 end
end
include TestAlias
_say
#From Top Level

结论:alias 会沿着继承链(父类,Mix-in,Kernel,Object,Top Level等)查找方法直到找不到方法时抛出No Method Error异常。(上面只举了一个Top Level的例子,其他情况类似)
最后自己hack了一下alias_method:

class Module
 alias _alias_method alias_method
 def alias_method alias_m, m
   define_method m do
     self.__send__ m
   end
   _alias_method alias_m, m
 end   
end

class TT
  #让alias_method放在前面也可以
  alias_method :_say, :say
  def say
    puts "say"
  end
end
TT.new._say
#say

PS:感觉最开始的代码用super比较不错..
class Adaptee
  def talk; puts 'Adaptee';end
end
class Adapter < Adaptee
  #alias talkee talk
  def talk
	puts 'before Adaptee'
	super
	puts 'after Adaptee'
  end
end
Adapter.new.talk

分享到:
评论
3 楼 areha001 2009-07-06  
alias b a


step1 : 桌面上有个叫 a 的文件夹
step2 : 我复制a并粘帖,重命名为b

def a
dosomething


step3 : 在C:\新建一个叫 a 的文件夹.往里面塞进几个自己要的文件
step4 : 把新打包好的压缩文件放到桌面,替换掉原有的a 文件夹


def a
dosomething
b
end


step5 : 把step2复制的 b 文件夹的所有文件再拷贝到 a 文件夹里.
2 楼 Hooopo 2009-06-27  
单纯从用alias避免在方法中调用继承链上与自身同名方法这个场景看,super无疑是最佳替代品。
1.显然这个场景里面super一定可用。

2.用super指定向继承链回溯的层数(好像alias做不到):

class Object
  #via:http://www.ruby-forum.com/topic/187339
  def super!(n,*args)
    method=caller[0][%r/.*?`(.*?)'/,1].to_sym
    klass=self.class.ancestors[n]
    klass.instance_method(method).bind(self).call(*args)
  end
end

class Adaptee
  def talk; puts 'Level 1';end
end

def talk
  puts "Level 2"
end
class Adapter < Adaptee
  def talk
	puts 'before Adaptee'
        #跳过父类的talk直接调用top leve的talk
	super! 2
	puts 'after Adaptee'
  end
end
Adapter.new.talk

#before Adaptee
#Level 2
#after Adaptee



1 楼 night_stalker 2009-06-27  
alias 总会让我想起《Alias》

能 super 自然最好,不能 super 就只好 alias 了 ……

相关推荐

Global site tag (gtag.js) - Google Analytics