Scala тип сопоставления с образцом с унаследованными классами - PullRequest
0 голосов
/ 07 мая 2020

У меня есть ряд унаследованных классов, у которых несколько больше методов, чем у базового класса. Вот так:

class Animal
{  
  var Name: String
}  
class Fish extends Animal
{  
  def swim()  
  {  
    println("I'm a Fish and i'm swimming!");  
  }
}
class Turtle extends Animal
{
  def swim()  
  {  
    println("I'm a Turtle and i'm swimming!");  
  }
}

Я хотел бы использовать шаблон сопоставления типов для класса generi c Animal, чтобы распознать точный тип и применить метод swim(), если это возможно, например :

myAnimal match {
  case m:Fish => m.Swim()
  case m:Turtle => m.Swim()
  case _: => doSomethingElse()
}

Я хотел бы написать это элегантно, избегая непрерывного повторения строк.

Я знаю, что могу это сделать:

myAnimal match {
  case (_:Fish | _:Turtle) => println("I can do this!")
}

И я знаю, как я писал выше, что я могу:

myAnimal match {
  case m:Fish => m.swim()
}

но я могу 'не вставляйте их или, вот так

myAnimal match {
  case (m:Fish | m:Turtle) => m.swim() //ERROR (cannot recognize swim() method)

  //Not even this
  case m @ (_:Fish | _:Turtle) => m.swim() //ERROR (cannot recognize swim() method)
  case _: => doSomethingElse()
}

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

1 Ответ

0 голосов
/ 07 мая 2020

Вы можете использовать структурные типы в сочетании с экстрактором, который использует отражение, чтобы проверить, имеет ли ваш объект метод swim. Благодаря Матеушу Кубушоку и Дмитрию Митину, теперь у меня есть решение, которое, кажется, работает. Ссылка на Scast ie

Однако я бы не рекомендовал это делать. Вероятно, проще провести рефакторинг вашего кода.

<script src="https://scastie.scala-lang.org/gFBe7jTQQiW3WnPVTJoFPw.js"></script>
...