【问题标题】:'super' and inheritance in RubyRuby 中的“超级”和继承
【发布时间】:2018-05-08 12:08:22
【问题描述】:

在下面的类继承设计中,类B继承类A,并评估其方法的参数:

class A
  def method_1(arg)
     puts "Using method_1 with argument value '#{arg}'"
  end

  def method_2(arg)
     method_1(arg)
  end
end

class B < A
   def method_1()
      super("foo")
   end

   def method_2()
      super("bar")
   end
end

这是我在尝试时得到的:

inst_A = A.new
inst_A.method_1("foo")
# >> Using method_1 with argument value 'foo'
inst_A.method_2("bar")
# >> Using method_1 with argument value 'bar'

我已经不明白了:

inst_B = B.new
inst_B.method_1
# >> Using method_1 with argument value 'foo'
inst_B.method_2
# >> Error: #<ArgumentError: wrong number of arguments (1 for 0)>
# >> <main>:11:in `method_1'
# >> <main>:6:in `method_2'
# >> <main>:16:in `method_2'

为什么在调用B#method_2 时调用B#method_1,而不是A#method_1

【问题讨论】:

  • 我猜你得到一个错误是因为 Ruby 不支持方法重载?当您继承 B
  • 如果您从消息发送的角度考虑会更容易。 method_1(arg) 将消息method_1 发送到self,即inst_B。然后 Ruby 搜索与该名称匹配的方法,从 B 的方法开始并找到 B#method_1

标签: ruby inheritance super


【解决方案1】:

我修改了您的示例以打印出A#method_1 中的当前类

def method_1(arg)
   puts "Using method_1 from class: '#{self.class}' with argument value '#{arg}'"
end

如果你调用B#method_1,你会得到这个输出

Using method_1 from class: 'B' with argument value 'foo'

正如你所说,它正在调用B#method_1(它会覆盖A#method_1)。这同样适用于B#method_2 调用super,然后尝试调用self#method_1,它不接受任何参数。在这种情况下,selfB 类型,B 覆盖 method_1 以不接受任何参数。

Ruby 首先尝试在self 中查找方法,如果找到就调用它,否则它会查看该对象的ancestors 并调用它找到的方法的第一个版本。在您的情况下,self 具有不带参数的 method_1,请记住 Ruby 不支持方法重载(除非您使用可选参数)。

【讨论】:

  • “请记住,Ruby 支持方法重载(除非您使用可选参数)” 为我确定了这一点。我天真地认为是这样,这就是我所有麻烦的根源。谢谢!
【解决方案2】:

method_2 在类 B 中调用 method_2(super) 在类 A 中,参数为 "bar"method_2A 类中(从 B 类中调用)调用 method_1B 类中,参数为 "bar"。来自B 类的method_1method_2 覆盖了来自A 类的同名。这就是调用继承类的method_1 的原因。

【讨论】:

  • OP 知道 B#method_1 被调用。问题是为什么?
猜你喜欢
  • 2017-05-02
  • 1970-01-01
  • 2021-01-29
  • 1970-01-01
  • 2018-05-03
  • 2014-09-02
  • 1970-01-01
  • 2018-04-26
  • 2017-04-05
相关资源
最近更新 更多