首页 > 解决方案 > 任何方式在声明中捕获常量的名称?

问题描述

我有一堂课。我们称它为 SomeClass:

class SomeClass
end

我不想以正常方式定义此类的实例,而是想使用一个常量来定义它们:

MyConstant = SomeClass.new

我也希望能够捕获某些类设置的常量的名称,这与标准 ruby​​ 类对 .class 方法所做的方式非常相似。

MyConstant.name #-> "MyConstant"

我希望能够这样做以从某个类的所有实例中呈现更好的错误消息,如下所示:

class SomeClass 
  def display_error_message 
    "Error, some class #{self.name} has a problem"
  end
end

MyConstant.display_error_message
#-> "Error, some class MyConstant has a problem"

有什么办法可以做到这一点?

编辑


这是一个示例,以阐明我的目标。

(Enum 是我正在创建的类的名称,它的作用类似于 Swifts 的“Enum”类型。基本上它使用 raw_value(“Pepperoni ", "Sausage", "Mushroom".) 显然,在这个例子中,一个散列或者一个简单的算法将一个符号转换为大写字母字符串是可行的,但实际上枚举类会做更多的事情,但是这个例子展示了它的要点。

class Pizza 
  attr_reader :topping

  Toppings = Enum.new do 
    option(:pepperoni).set("Pepperoni")
    option(:sausage).set("Sausage")
    option(:mushrooms).set("Mushrooms")
  end

  def set_topping(symbol)
    @topping = Toppings[symbol]
  end
end

pizza = Pizza.new

### Happy Case
pizza.set_topping(:pepperoni)

### Sad Case (Error message shown below is what I'm trying to figure out)
pizza.set_topping(:spinach)
#-> Error. enum Toppings has no option spinach

标签: ruby

解决方案


变量只是引用对象的一种方式,变量的名称无关紧要。如果你说X = YandY恰好是一个类,那么这个Y类已经有了 name "Y",所以你不能改变它。

就 Ruby 而言XY它们是无法区分的。

如果您想更改名称,即使该子类没有做任何不同的事情,您也可以创建一个子类:

X = Class.new(Y)
X.name
# => "X"
Z = X
Z.name
# => "X"

这样可以正确保留名称,但仅在初始化的上下文中。我认为 Ruby 做了一些鬼鬼祟祟的事情,如果一个新类被分配给一个常量,它会分配一个名称,但对于普通变量它不会:

x = Class.new(Y)
x.name
# => nil

所以这是一个特例。

这里的关键是子类之间存在巨大差异,它确实会影响名称,而变量引用则不会。

这里发生了一些其他奇怪的事情,因为似乎该类以某种方式“知道”它何时被分配给某物,并且如果该某物是常量,它会为自己窃取常量的名称:

z = Class.new
z.name
# => nil
Z = z
z.name
# => "Z"

正如他们在编程中所说:“Wat?”


推荐阅读