Crystal: как реализовать несколько абстрактных методов с одним методом в дочернем? - PullRequest
1 голос
/ 10 мая 2019

Предположим, у меня есть абстрактная структура, которая должна работать с двумя типами входных данных, например так (подробнее см. предыдущий вопрос SO ).

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

Если моя реализация можетиспользуйте self и Num взаимозаменяемо, кажется разумным просто сложить их вместе:

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 требование абстрактного класса.

Вы можете увидеть на этой игровой площадке .

Есть ли способ объединить их так, как я хочу?Я бы предпочел не дублировать код без необходимости (т.е. следующие компиляции, но мне это не нравится):

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 ]

1 голос
/ 10 мая 2019

Это довольно простое решение, но, вероятно, не такое чистое, как простое разделение двух методов. play Вам просто нужно было изменить абстрактный метод на кортеж вместо двух отдельных методов.

0 голосов
/ 20 мая 2019

Лучшее, что я смог придумать, - это определить метод join в абстрактном классе, чем-то похожий на то, о чем говорит Самуал.Если все сделано таким образом, реализующие структуры могут свободно определять каждую отдельно или все вместе.

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 / # / г / 6y3j

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...