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

纵然是瞬间 提交于 2019-12-11 12:52:56

问题


Suppose I have an abstract struct that needs to operate on two kinds of inputs like so (for more context, see previous SO question).

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

If my implementation can use self and Num interchangeably, it seems reasonable to just put them together:

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

The truth is though that since the type is self | Num it matches neither the self nor the Num requirement of the abstract class.

You can see for yourself in this playground.

Is there a way to combine these like I want? I'd rather not duplicate the code unnecessarily (i.e. the following compiles but I don't like it):

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

回答1:


It is quite a simple solve, but is probably not as clean as just separating the two methods. play You just needed to change the abstract method to be a tuple instead of two separate methods.




回答2:


The best I've been able to come up with, is to define the joined method in the abstract class, somewhat similar to what Samual is talking about. If done this way, the implementing structs are free to define each separately or all combined.

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

The way this works is that if they are defined separately by you, then the combined method comes along for type safety but isn't used. If you define them together, you override the third method, but the other two won't give you trouble because a program which satisfies the third condition satisfies the first two.

Here's a demonstration: https://play.crystal-lang.org/#/r/6y3j



来源:https://stackoverflow.com/questions/56074831/crystal-how-to-implement-multiple-abstract-methods-with-one-method-in-child

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!