Комментарии 11
Приём с наследником sealed класса в java — интересный.
Но конкретно для option можно вместо Option(null), который вернёт None, вызвать Some(null) и получить примерно те же эффекты.
Я, наверное, чего-то не понимаю, но почему sealed
-класс в Scala не является final
-классом в Java? Из-за этого ведь все проблемы.
А в этом случае JVM разве не ругнётся на то, что от него кто-то отнаследовался в Scala?
А разве в Scala можно отнаследоваться от Option
? Статья же говорит, что нет, ведь он sealed
.
Извне — нельзя, но внутри того же пакета у него есть наследники — case class Some и case object None. Я пытаюсь понять, если при компиляции Scala объявит Option как final, примет ли JVM наличие Some и None?
Ах, вот оно в чём дело… Я со Scala'ой не знаком, потому мне и непонятно было, почему sealed
-классы не былы сделаны final
'ьными. Но раз есть (приватные?) наследники, выходит, по-другому сделать было нельзя.
Что интересно, sealed классы в kotlin'e таким образом не сломаешь — конструктор у базового класса помечен как synthetic, что делает невозможным его вызов из Java (да и других jvm языков) без применения особой уличной магии.
Почему в скале не сделали так-же — непонятно, вполне очевидная штука.
sealed class Option {
class Some<out T>(val value: T) : Option()
object None : Option()
}
import kotlin.jvm.internal.DefaultConstructorMarker;
public abstract class Option {
private Option() {
}
public /* synthetic */ Option(DefaultConstructorMarker $constructor_marker) {
this();
}
public static final class Some<T>
extends Option {
private final T value;
public final T getValue() {
return this.value;
}
public Some(T value) {
super(null);
this.value = value;
}
}
public static final class None
extends Option {
public static final None INSTANCE;
private None() {
super(null);
}
static {
None none;
INSTANCE = none = new None();
}
}
}
Котлин более свежий язык. Я думаю, что они как раз учли ошибки других JVM языков. Ну по крайней мере постарались. И в Котлин версии уже хаки грязные не проходят. Хотя конечно сложно представить, что кто-то будет такой ад пытаться сделать в продакшен коде.
Это не меняет ситуации с данной конкретной проблемой. Разработчики jvm языков вполне осведомлены о наличии synthetic, который был с лохматых времён (в 1.5 точно был, возможно даже раньше, если не с 1.0), и активно им пользуются в других местах.
Добавление synthetic не ломает abi (разве что api для случаев, описанных в статье, но кого волнует совместимость с теми, кто в обход скалы пытается отнаследоваться от sealed?), его вполне можно добавить хоть прямо сейчас в компилятор.
Null подкрался незаметно: ломаем Scala Option с помощью Java