我上课了。我们称之为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'类型。基本上它设置了一个预定义的选项列表(:pepperoni,:sausage,:mushroom)和raw_value (“Pepperoni”,“Sausage”,“Mushroom”。)显然在这个例子中,用于将符号转换为UpperCamel案例字符串的哈希或简单算法可以工作,但实际上enum类会做更多,但是这个示例显示了它的要点。
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
答案 0 :(得分:4)
变量只是引用对象的一种方式,变量的名称是无关紧要的。如果您说X = Y
和Y
恰好是一个班级,那么Y
班级已经有"Y"
名称,因此您无法更改该名称。
就Ruby而言X
和Y
无法区分。
如果要更改名称,即使该子类没有做任何不同的操作,也可以创建一个子类:
X = Class.new(Y)
X.name
# => "X"
Z = X
Z.name
# => "X"
这样可以正确保留名称,但仅限于初始化的上下文中。我认为Ruby做了一些偷偷摸摸的事情,如果将一个新类分配给一个常量,它会分配一个名称,但对于普通变量,它不会:
x = Class.new(Y)
x.name
# => nil
所以这是一个特例。
这里的关键是,确实影响名称的子类与不具有变量引用的子类之间存在巨大差异。
还有其他一些奇怪的东西在这里,因为它看起来像某种程度上的类#34;知道"如果它被分配给某个东西,并且如果某个东西是一个常数,它会为自己窃取常数的名称:
z = Class.new
z.name
# => nil
Z = z
z.name
# => "Z"
正如他们在编程中所说:" Wat?"
答案 1 :(得分:1)
您的<div class="dropdown">
<button onclick="myFunction(event)" class="dropbtn">Dropdown</button>
<div id="myDropdown"
onclick="event.stopPropagation()"
class="dropdown-content">
<label><input type="checkbox" value="Vanilla">Vanilla</label>
<label><input type="checkbox" value="Chocolate">Chocolate</label>
<label><input type="checkbox" value="Strawberry">Strawberry</label>
</div>
</div>
<style>
.dropbtn {
background-color: #4CAF50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropbtn:hover {
background-color: #3e8e41;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #fff;
min-width: 230px;
overflow: auto;
border: 1px solid #ddd;
z-index: 1;
}
label {
display: block;
padding: 12px 16px;
}
.show {
display:block;
}
</style>
<script>
function myFunction(e) {
e.stopPropagation();
document.getElementById("myDropdown").classList.toggle("show");
}
document.addEventListener('click', () => {
document.getElementById("myDropdown").classList.remove("show");
})
</script>
课程可能如下所示:
Enum
现在,您几乎可以保留问题中的语法,并执行以下操作:
class Enum
def initialize(name, &blk)
@defined_options = {}
@name = name.freeze
instance_eval(&blk)
@defined_options.freeze
end
def [](key)
if @defined_options.key? key
@defined_options[key].value
else
unfound_option = Option.new(@name, key)
raise "Option #{unfound_option} not found."
end
end
def to_s
"#{@name}"
end
def inspect
keys = @defined_options.keys.join(',')
"#<#{self}::{#{keys}}>"
end
class Option
attr_reader :value
def initialize(enum_name, key)
@value_initialized = false
@enum_name = enum_name
@key = key
end
def set(value)
if @value_initialized
raise "Value for #{self} can't be set to #{value} " +
"because it is already initialized to #{@value}"
else
@value_initialized = true
@value = value.freeze
end
end
def to_s
"#{@enum_name}::#{@key}"
end
def inspect
"#<#{self}>"
end
end
private
def option(sym)
unless @defined_options.key? sym
option = Option.new(@name, sym)
@defined_options[sym] = option
end
@defined_options[sym]
end
end
这可能会让您了解如何解决此问题。这只是课程的粗略草图,可能会根据您的需要进行调整。