Crystal: 如何在child中用一个方法实现多个抽象方法?

Crystal: how to implement multiple abstract methods with one method in child?

假设我有一个抽象结构需要像这样对两种输入进行操作(有关更多上下文,请参阅 previous SO question)。

abstract struct Numberlike
  alias Num = (Int32 | Float64)
  abstract def -
  abstract def -(other : self)
  abstract def -(other : Num)
end

如果我的实现可以互换使用selfNum,那么将它们放在一起似乎是合理的:

struct Term < Numberlike
  alias Num = (Int32 | Float64)
  getter coeff : Num
  getter sym : Symbol

  def initialize(@coeff, @sym); end

  def -(other : self | Num)
    self.class.new(coeff - other, sym)
  end

  def -
    self.class.new(-coeff, sym)
  end
end

事实是,由于类型是 self | Num,它既不符合摘要 class 的 self 要求,也不符合 Num 要求。

您可以在 this playground 中亲自查看。

有没有办法像我想要的那样组合这些?我不想不必要地复制代码(即以下编译但我不喜欢它):

struct Term < Numberlike
  alias Num = (Int32 | Float64)
  getter coeff : Num
  getter sym : Symbol

  def initialize(@coeff, @sym); end

  def -(other : self)
    self.class.new(coeff - other, sym)
  end

  def -(other : Num)
    self.class.new(coeff - other, sym)
  end

  def -
    self.class.new(-coeff, sym)
  end
end

这是一个非常简单的解决方案,但可能不如将两种方法分开那么干净。 play 您只需要将抽象方法更改为一个元组,而不是两个单独的方法。

我能想到的最好的方法是在抽象中定义连接方法 class,有点类似于 Samual 所说的。如果这样做,实现结构可以自由定义每个单独或全部组合。

abstract struct Addable
  abstract def +(other : self)
  abstract def +(other : Int32)
  def +(other : self | Int32)
    if other.is_a?(Int32) ? self + other : self + other
  end
end

它的工作方式是,如果它们由您单独定义,那么组合方法会出现以确保类型安全,但不会使用。如果你一起定义它们,你覆盖了第三个方法,但其他两个不会给你带来麻烦,因为满足第三个条件的程序满足前两个。

这里有一个演示:https://play.crystal-lang.org/#/r/6y3j