Я считаю, что 1 и 2 компилируются в один и тот же байт-код (кроме имени класса, которое генерируется в случае 2).
Если Fooable существует только для того, чтобы вы могли неявно преобразовать A в Fooable (и вы никогда не собираетесь напрямую создавать и использовать Fooable), то я бы выбрал вариант 2.
Однако, если вы управляете A (имеется в виду, что A не является классом библиотеки Java, который не может быть подклассом), я бы рассмотрел использование черты вместо неявных преобразований для добавления поведения в A.
UPDATE :
Я должен пересмотреть мой ответ. Я бы использовал вариант 1 вашего кода, потому что вариант 2, как оказалось, использует отражение (scala 2.8.1 в Linux).
Я скомпилировал эти две версии одного и того же кода, декомпилировал их в java с помощью jd-gui, и вот результаты:
исходный код с именованным классом
class NamedClass { def Foo : String = "foo" }
object test {
implicit def StrToFooable(a: String) = new NamedClass
def main(args: Array[String]) { println("bar".Foo) }
}
исходный код с анонимным классом
object test {
implicit def StrToFooable(a: String) = new { def Foo : String = "foo" }
def main(args: Array[String]) { println("bar".Foo) }
}
скомпилировано и декомпилировано в java с помощью java-gui. «Именованная» версия генерирует NamedClass.class, который декомпилируется в эту Java:
public class NamedClass
implements ScalaObject
{
public String Foo()
{
return "foo";
}
}
аноним генерирует тестовый класс $$ anon $ 1, который декомпилируется в следующую Java
public final class test$$anon$1
{
public String Foo()
{
return "foo";
}
}
так почти идентично, за исключением того, что аноним является "окончательным" (они, очевидно, хотят убедиться, что вы не сделаете все возможное, чтобы попытаться создать подкласс анонимного класса ...)
однако на сайте вызова я получаю эту Java для "именованной" версии
public void main(String[] args)
{
Predef..MODULE$.println(StrToFooable("bar").Foo());
}
и это для анонима
public void main(String[] args) {
Object qual1 = StrToFooable("bar"); Object exceptionResult1 = null;
try {
exceptionResult1 = reflMethod$Method1(qual1.getClass()).invoke(qual1, new Object[0]);
Predef..MODULE$.println((String)exceptionResult1);
return;
} catch (InvocationTargetException localInvocationTargetException) {
throw localInvocationTargetException.getCause();
}
}
Я немного погуглил и обнаружил, что другие сообщили об одном и том же, но я не нашел больше информации о том, почему это так.