Я считаю, что 1 и 2 компилируются в один и тот же байт-код (за исключением имени класса, которое генерируется в случае 2). Если Fooable существует только для того, чтобы вы могли неявно преобразовать A в Fooable (и вы никогда не собираетесь напрямую создавать и использовать Fooable), то я бы выбрал вариант 2.
Однако, если вы управляете A (это означает, что A не является классом библиотеки Java, который вы не можете подклассировать), я бы подумал об использовании типажа вместо неявных преобразований, чтобы добавить поведение к A.
ОБНОВЛЕНИЕ: я должен пересмотреть свой ответ. Я бы использовал вариант 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";
}
}
анонимный генерирует класс test$$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();
}
}
Я немного погуглил и обнаружил, что другие сообщал то же самое, но я не нашел больше информации о том, почему это так.
person
Paolo Falabella
schedule
07.03.2011