使用字符串可以做到这一点:
a = "hello"
a.upcase!
p a #=> "HELLO"
但是我该如何编写自己的方法呢?
类似的东西(虽然这显然不起作用):
class MyClass
def positify!
self = [0, self].max
end
end
我知道可以在String上使用一些技巧,但是如果我尝试为Object执行类似的操作呢?
答案 0 :(得分:7)
许多类都是不可变的(例如Numeric
,Symbol
,...),因此没有允许您更改其值的方法。
另一方面,任何Object
都可以包含实例变量,这些变量可以修改。
有一种简单的方法可以将行为委派给已知对象(比如42
),并且可以使用SimpleDelegator
稍后更改为另一个对象。在下面的示例中,quacks_like_an_int
的行为类似于Integer
:
require 'delegate'
quacks_like_an_int = SimpleDelegator.new(42)
quacks_like_an_int.round(-1) # => 40
quacks_like_an_int.__setobj__(666)
quacks_like_an_int.round(-1) # => 670
您也可以使用它来设计一个类,例如:
require 'delegate'
class MutableInteger < SimpleDelegator
def plus_plus!
__setobj__(self + 1)
self
end
def positify!
__setobj__(0) if self < 0
self
end
end
i = MutableInteger.new(-42)
i.plus_plus! # => -41
i.positify! # => 0
答案 1 :(得分:4)
嗯,upcase!
方法不会更改对象标识,只会更改其内部结构(s.object_id == s.upcase!.object_id
)。
另一方面,数字是不可变对象,因此,您无法在不更改其身份的情况下更改其值。 AFAIK,对象无法自我更改其身份,但是,当然,您可以实现更改其对象属性的positify!
方法 - 而此将类似于怎么了!为字符串做。
答案 2 :(得分:2)
本地变量的赋值或绑定(使用=
运算符)内置于核心语言中,无法覆盖或自定义它。您可以在Ruby代码上运行预处理器,这会将您自己的自定义语法转换为有效的Ruby。您还可以将Binding
传递给自定义方法,该方法可以动态重新定义变量。但是,这不会达到你想要的效果。
明白self =
永远不会有效,因为当你说a = "string"; a = "another string"
时你没有修改任何对象;您将局部变量重新绑定到另一个对象。在自定义方法中,您处于不同的范围内,并且您绑定的任何局部变量将仅存在于该范围内的 ;它不会对您调用方法的范围产生任何影响。
答案 3 :(得分:2)
您不能将self更改为指向除当前对象之外的任何内容。您可以更改实例变量,例如在将基础字符更改为大写字母的大小写字符串中。
正如这个回答所指出: Ruby and modifying self for a Float instance
这里提到的一个技巧是解决方法,即将您的类编写为另一个对象的包装器。然后你的包装类可以随意替换包装对象。我犹豫是否说这是一个好主意。