水晶:如何实现与孩子的一种方法多种抽象方法?(Crystal: how to implement m

2019-09-27 20:32发布

假设我有一个需要对两种输入像这样操作一个抽象的结构(更多的情况下,看到前面的SO问题 )。

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它匹配既不是self ,也不是Num抽象类的要求。

你可以看到自己这个操场 。

有没有办法将这些像我想结合? 我宁愿不重复的不必要的代码(即下面的编译但我不喜欢它):

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

Answer 1:

这是一个非常简单的解决,但可能并不像这两种方法分离干净。 发挥你只需要改变抽象方法是一个元组,而不是两个独立的方法。



Answer 2:

我已经能够拿出最好的,是定义在抽象类中加入方法,有点类似塞穆尔什么都在谈论。 如果做到了这一点的方式,执行结构可以自由定义每个单独或合并所有。

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



文章来源: Crystal: how to implement multiple abstract methods with one method in child?