Ruby 中的 alias 关键字

yufei       5 年, 6 月 前       1805

alias,别名,顾名思义,就是给某个东西取一个别名。比如我,小时候,穿的破破烂烂,然后发行又长的有点像济公。因此家里的邻居每次都是 济公 济公的叫我。

心累啊。

Ruby 把 alias 提升到了关键字级别。作用也跟它的意思一样。本章节,我们将会讲述和 Ruby alias 关键字有关的以下内容

  • alias 关键字
  • alias_method 方法
  • 别名和作用域
  • 别名背后的逻辑

Ruby 中的 alias 关键字

一句话解释 Ruby 中的 alias 关键字的作用: 用于给方法和属性定义一个别名

比如我们有一个类 User ,定义如下

demo.rb

class User
  def fullname
    'John Doe'
  end
end

User 类中的 fullname 对于程序来说并不直观,可能别人想要的是 username ,而 username 实际上就是 fullname ,如果不使用别名,我们一般会如下定义

class User
  def fullname
    '简单教程,简单编程'
  end

  def username
    fullname
  end
end

看到多出来的一个方法,我们内心是崩溃的,作为现代语言,Ruby 肯定是不允许这样的存在,因此,它提供了 alias 关键字,用来定义别名。

alias 关键字的语法格式如下

alias [新的名称] [已经存在的方法名或属性名或别名]

比如,我们可以使用 alias 关键来改造上面的代码

class User
  def fullname
    '简单教程,简单编程'
  end

  alias username fullname
end

我们完善下代码,写一个示例运行下

demo.py

class User
  def fullname
    '简单教程,简单编程'
  end

  alias username fullname
end

u = User.new

p u.fullname
p u.username

运行结果如下

[root@www.twle.cn ruby] ruby demo.rb
"简单教程,简单编程"
"简单教程,简单编程"

另外,alias 还可以对一个别名在创建一个别名,比如

class User
  def fullname
    '简单教程,简单编程'
  end

  alias username fullname
  alias name   username
end

u = User.new

p u.fullname
p u.username
p u.name

运行结果如下

[root@www.twle.cn ruby] ruby demo.rb
"简单教程,简单编程"
"简单教程,简单编程"
"简单教程,简单编程"

Ruby alias_method 方法

Ruby 除了可以使用 alias 关键字来定义别名外,还可以使用 alias_method 方法来创建一个别名。

alias_method 方法的原型如下

lias_method(new_name, old_name)  self click to toggle source

参数和关键字顺序与 alias 关键字是一样的。

我们写一小段代码来演示下 alias_method 方法的使用

ruby

class User
  def fullname
    '简单教程,简单编程'
  end

  alias_method :username, :fullname
  alias_method 'name',:username
end

u = User.new

p u.fullname
p u.username
p u.name

运行结果如下

[root@www.twle.cn ruby] ruby demo.rb
"简单教程,简单编程"
"简单教程,简单编程"
"简单教程,简单编程"

如果你比较细心,你会发现 alias_method 方法的参数是要么是一个 symbol ,要么就是一个字符串。这是和使用 alias 关键字最大的不同。如果我们把代码改成下面这样

class User
  def fullname
    '简单教程,简单编程'
  end

  alias_method username, :fullname
  alias_method 'name',:username
end

u = User.new

p u.fullname
p u.username
p u.name

运行就会报错

[root@www.twle.cn ruby] ruby demo.rb
demo.rb:6:in `<class:User>': undefined local variable or method `username' for User:Class (NameError)
    from demo.rb:1:in `<main>'

你也许很疑惑,既然 alias 关键字和 alias_method 方法都共享着相同的行为,那为什么 alias 关键字和 alias_method 方法会同时存在呢,这不是多此一举吗?

哈哈,的确,从表面上看起来的确多此一举,但它们有着本质的区别,它们的区别就是别名的作用域问题

别名和作用域

aliasalias_method 是相同的,但又是不同的,如果非要说什么不同,那就是只有一个,就是创建的别名的作用域不同。

准确的来说,aliasalias_method 两个不同点在于继承体系中,对旧名字的引用是当前类的下名字还是祖先链中同一个类中定义的名字。

是不是有点难以理解,我们写两个范例来演示下:

demo.rb

class Device
  def description
    '简单教程'
  end

  def self.alias_description
    alias describe description
  end
end

class Microwave < Device
  def description
    '简单教程,简单编程'
  end

  alias_description
end

m = Microwave.new

p m.description
p m.describe

运行结果如下

[root@www.twle.cn ruby] ruby demo.rb
"简单教程,简单编程"
"简单教程"

从运行结果中可以看出,alias 关键字的别名,始终是在定义别名时作用域下的属性和名字。

我们在看看 alias_method 方法

class Device
  def description
    '简单教程'
  end

  def self.alias_description
    alias_method :describe,:description
  end
end

class Microwave < Device
  def description
    '简单教程,简单编程'
  end

  alias_description
end

m = Microwave.new

p m.description
p m.describe

运行结果如下

[root@www.twle.cn ruby] ruby demo.rb
"简单教程,简单编程"
"简单教程,简单编程"

从运行结果中可以看出,alias_method 方法,别名的使用是当前调用类中的属性名或方法。

别名背后的逻辑

现在,你是不是很好奇 aliasalias_method 两个别名的实现。哈哈,不要着急,为了理解它们背后的逻辑,我们得有耐心

我们先回到最开始的那个 alias 关键字的例子

demo.rb

class User
  def fullname
    '简单教程,简单编程'
  end

  alias username fullname
end

u = User.new

p u.fullname
p u.username

在这个范例中, 别名 username 可以看成是重新定义了一个相同实现的方法。

实际上,Ruby 存在一个表 method_entry 中,每个方法都插入到这个表中,我们可以使用该表跟踪程序的所有方法。

但我们使用 def 关键字创建了 fullname 方法时,会在 method_entry 表中插入一个新条目。此条目包含以下信息

  • :fullname 符号标识符
  • User#fullname 方法
  • User 类名

当调用 alias username fullname 生成一个别名时,也会在 method_entry 表中插入一个新条目。此条目包含以下信息

  • :usename 符号标识符
  • User#fullname 方法
  • User 类名

这就是 aliasalias_method 创建别名的逻辑,是不是很简单。

目前尚无回复
简单教程 = 简单教程,简单编程
简单教程 是一个关于技术和学习的地方
现在注册
已注册用户请 登入
关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.