我正在学习ruby,并发现无法创建名为puts
的类方法:
class Printer
def initialize(text="")
@text = text
end
def puts
puts @text
end
end
错误是:
`puts': wrong number of arguments (given 1, expected 0)
我的期望是我可以使用如下代码:
p = Printer.new("hello")
p.puts
这不仅是因为puts
是一种内置方法。例如,此代码还给出了语法错误:
def my_puts(text)
puts text
end
class Printer
def initialize(text="")
@text = text
end
def my_puts
my_puts @name
end
end
答案 0 :(得分:1)
tldr ;在实例范围内,puts
解析为self.puts
(然后解析为本地定义的方法,而不是Kernel#puts)。这种方法覆盖是 shadowing 的一种形式。
Ruby有一个'implicit self',它是这种行为的基础,并且是also how the bare puts
is resolved-它来自内核,它混入每个对象中。
Object类包含Kernel模块,因此每个Ruby对象都可以使用其方法[如Kernel#puts]。这些方法在没有接收方的情况下被调用,因此可以以功能形式(例如
puts
进行调用,除非它们被重写)。
要在此处调用原始的同名方法,可以使用super
关键字。但是,这在X#another_method 期望调用内核#puts时使用参数调用X#puts的情况下不起作用。要解决这种情况,请参见Calling method in parent class from subclass methods in Ruby(在适当的类型上使用别名或instance_method)。
class X
def puts
super "hello!"
end
end
X.new.puts
P.S。第二个示例应该会失败,因为my_puts
显然不带任何参数,而不会引起其他“输入”的混淆。而且,它不是语法错误,因为它是在任何语言解析后在运行时发生的。
答案 1 :(得分:1)
要添加到上一个答案(https://stackoverflow.com/a/62268877/13708583),一种解决方法是为在新puts方法中使用的原始puts创建别名。
class Printer
alias_method :original_puts, :puts
attr_reader :text
def initialize(text="")
@text = text
end
def puts
original_puts text
end
end
Printer.new("Hello World").puts
您可能对其他(静态)编程语言感到困惑,在这些语言中,您可以通过创建不同的签名来覆盖方法。
例如,这只会在Ruby中创建一个puts方法(在Java中,您将有两个puts方法(免责声明:不是Java专家)。
def puts(value)
end
def puts
end
如果您要使用其他名称相同但接受不同参数的方法,则需要使用以下可选方法参数:
def value(value = "default value")
end