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

时间:2019-05-10 09:39:10

标签: inheritance abstract crystal-lang

假设我有一个抽象结构,需要像这样对两种输入进行操作(有关更多上下文,请参见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,因此它既不符合抽象类的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

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

我能想到的最好的办法是在抽象类中定义join方法,这与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