Избегание явного делегирования при использовании имплицитов для реализации признака


Я использую несколько таких классов:

class MyClassOne {
  doSomething(a : A) : B
  ... 
} 

class MyClassTwo {
  doSomething(a : A) : B
  ... 
} 

Источник для классов не находится под моим контролем. Хотя классы имеют методы с той же сигнатурой, они не реализуют интерфейс. Я хотел бы определить методы, которые работают на всех классах.

Итак, я сделал такую черту:

trait MyTrait {
  doSomething(a : A) : B
}

И произвели неявные преобразования для всех классов:

implicit class MyClassOneMyTrait(myClassOne : MyClassOne) {
  def doSomething(a : A) = myClassOne.doSomething(a)
}

Есть ли способ воспользоваться преимуществами соглашений об именовании, используемых в классах, и избежать явное делегирование объектов, переданных в конструктор? В более общем плане, является ли использование признака с неявными классами лучшим подходом к этой проблеме?

1 2

1 ответ:

На самом деле, есть функция scala именно для вашей ситуации. Это называетсяструктурные типы .

Для структурных типов требования к типу выражаются структурой интерфейса вместо конкретного типа. Внутренняя реализация использует рефлексию, поэтому будьте внимательны к производительности!
type A = String
type B = String

class MyClassOne {
  def doSomething(a: A): B = {
    println("1")
    "1"
  }
}

class MyClassTwo {
  def doSomething(a: A): B = {
    println("2")
    "2"
  }
}

type MyClassType = {
  def doSomething(a: A): B
}

List[MyClassType](new MyClassOne, new MyClassTwo).foreach(_.doSomething("test"))
List(new MyClassOne, new MyClassTwo).foreach {
  case a: MyClassType => a.doSomething("test")
  case _ =>
}