LINUX.ORG.RU

Разобрался зачем нужны Sealed Classes в Java

 


4

2
sealed interface AsyncReturn<V> {
    record Success<V>(V result) implements AsyncReturn<V> { }
    record Failure<V>(Throwable cause) implements AsyncReturn<V> { }
    record Timeout<V>() implements AsyncReturn<V> { }
    record Interrupted<V>() implements AsyncReturn<V> { }
}
AsyncResult<V> r = future.get();
switch (r) {
    case Success<V>(var result): ...
    case Failure<V>(Throwable cause): ...
    case Timeout<V>(): ...
    case Interrupted<V>(): ...
}

Раньше для этого enum-ы городил, а теперь у нас как в ржавом можно запиливать ) Такие дела, век живи - век учись.

А еще Гослинг хочет нормальный синтаксис для модификации рекордов (и видимо будущих иммутабельных value type) запилить типа:

Foo foo = new Foo(10, 20)
Foo bar = foo with { x:12}

Но это уже совсем другая история.

★★★★★

Последнее исправление: foror (всего исправлений: 2)

Ответ на: комментарий от korvin_

Я тогда по диагонали глянул и не понял зачем оно нужно. А щас на реальных примерах как понял…

foror ★★★★★
() автор топика
Ответ на: комментарий от korvin_
sealed interface Celestial 
    permits Planet, Star, Comet { ... }

final class Planet implements Celestial { ... }
final class Star   implements Celestial { ... }
final class Comet  implements Celestial { ... }

Ну, вот зачем эта хренопляска? Не, я еще понимаю для внутренней кухни JDK:

public sealed interface ConstantDesc
    permits String, Integer, Float, Long, Double,
            ClassDesc, MethodTypeDesc, DynamicConstantDesc { ... }

С такими мыслями я и ушел с того JEP-a. А вот это вообще не в концепции джавы:

Shape rotate(Shape shape, double angle) {
    return switch (shape) {   // pattern matching switch
        case Circle c    -> c; // за такой код постучать по голове разрабов
        case Rectangle r -> shape.rotate(angle);
        case Square s    -> shape.rotate(angle);
        // no default needed!
    }
}
foror ★★★★★
() автор топика
Последнее исправление: foror (всего исправлений: 2)
Ответ на: комментарий от korvin_

https://en.wikipedia.org/wiki/Polymorphism_(computer_science)

https://en.wikipedia.org/wiki/Tagged_union

able to verify that all cases of a tagged union are always handled, avoiding many types of errors

avoiding many types of errors

То я и вижу, как код с фигурами начинает круги вращать.

foror ★★★★★
() автор топика
Последнее исправление: foror (всего исправлений: 2)
Ответ на: комментарий от korvin_

Для себя я в топике обозначил область применения данной фичи. Ударяться в крайности с полной заменой полиморфизма это очень глупо. Но не будем здесь про ржавый.

foror ★★★★★
() автор топика
Последнее исправление: foror (всего исправлений: 2)
Ответ на: комментарий от foror

Полиморфизм тут не совсем к месту. У них (pm, tu) несколько разные случаи применения.

korvin_ ★★★★★
()
Ответ на: комментарий от foror

Ударяться в крайности с полной заменой полиморфизма это очень глупо.

А кто предлагает удариться в такую крайность?

korvin_ ★★★★★
()
Ответ на: комментарий от foror

Что не так? Если кругу не положено текстуры или иных опознавательных знаков, то его вращение вполне может быть пустой операцией.

KivApple ★★★★★
()
Ответ на: комментарий от KivApple

Если кругу не положено текстуры или иных опознавательных знаков

А если положено? Правильнее было бы сделать условное Rotatable и реализовать Circle::rotate в виде noop.

Siborgium ★★★★★
()
Ответ на: комментарий от KivApple

Что не так?

Код допускает отправку круга для операции вращения, которая по коду не предусмотрена. Значит сделай выброс UnsupportedOperationException, чтобы в твоём GUI если и начнут вращать круги, то было понятно, что делать это нельзя. Тем самым фронтендеры получат по макушке и доработают GUI.

foror ★★★★★
() автор топика

Я в вашей жабе не силён, но это же просто sum type. Они в ML и прочих хачкеллях уже лет 40 как есть.

hateyoufeel ★★★★★
()
Ответ на: комментарий от hateyoufeel

Так мы на джаве разрабы простые, которым не шашечки, а ехать. Но если пару шашечек подвезут страшно не будет, а только красивше код зацветёт.

foror ★★★★★
() автор топика
Ответ на: комментарий от foror

Код допускает отправку круга для операции вращения, которая по коду не предусмотрена. Значит сделай выброс UnsupportedOperationException, чтобы в твоём GUI если и начнут вращать круги, то было понятно, что делать это нельзя. Тем самым фронтендеры получат по макушке и доработают GUI.

А в каких редакторах к кругу нельзя применить операцию вращения?

По коду она не «не предусмотрена», а «ничего не делает».

korvin_ ★★★★★
()
Ответ на: комментарий от foror

Только едете вы медленно, и в итоге пока доедете, товар протух и его пожрали крысы, а пассажиры умерли от старости.

hateyoufeel ★★★★★
()
Ответ на: комментарий от hateyoufeel

Только вот указанный функционал реализован средствами языка, а не прибит гвоздями. В частности, указанный выше интерфейс можно сделать открытым (не-sealed), что в сумме дает средство куда более мощное, чем закрытый enum/data/etc.

Siborgium ★★★★★
()
Последнее исправление: Siborgium (всего исправлений: 1)
Ответ на: комментарий от Sunil

Не будет. Жава берет адекватные идеи, но не все, а те, которые доказали свою пользу.

За исключением checked exceptions. Это был большой промах.

vbr ★★★★
()
Ответ на: комментарий от Siborgium

Но в итоге это будет означать, что будет несколько конкурирующих реализаций, в каждой из которых будут свои косяки, и они будут несовместимы друг с другом. Знаем, проходили.

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 1)

sealed-типы нужны для того, чтобы ты мог сделать pattern matching с гарантированной проверкой всех вариантов. То есть ты не сможешь не проверить часть тех типов, которые расширяют sealed-тип.

LongLiveUbuntu ★★★★★
()
Ответ на: комментарий от Sunil

На гораздо худшем, ты хотел сказать. Зачем городить из Java Scala'у - решительно непонятно.

LongLiveUbuntu ★★★★★
()
Ответ на: комментарий от hateyoufeel

Реализаций чего?

в каждой из которых будут свои косяки

Какие?

и они будут несовместимы друг с другом

Какая разница?

Siborgium ★★★★★
()
Ответ на: комментарий от Siborgium

можно сделать открытым (не-sealed), что в сумме дает средство куда более мощное, чем закрытый enum/data/etc.

Каждое слово в хорошем языке что-то да означает. Если написано «не влезай - убьёт», то убирать его глупо. Sealed в данном случае означает, что куча кода завязано на идее о том, что список вариантов можно перебрать руками. Да и вообще, лучше ли открытый - это бабушка надвое сказала, это в теории полиморфизм работает хорошо, а на практике всё часто выливается в виртуальные методы типа шаг5функцииX, beforeX/afterX или prepareForX, т.е. просто те же ad hoc куски под конкретные задачи, которые просто разбросаны по разным классам и не несут какого-то смысла в рамках описываемого объекта.

Вот взять твой пример с ротатабле. Круг может вращаться в некотором контексте, а в некотором нужно сообщить GUI, что это не одобряется. В итоге в классе для круга появляются всякие невменяемые методы, не имеющие никакого отношения к понятию «круг». И даже мнимая расширяемость на самом деле нифига не работает. Вот захочу я написать класс Trapezoid, компилятор мне подскажет каких методов не хватает, ну я и, пользуясь логикой, напишу реализацию их, в соответствии с названиями. И откуда мне знать, что 14й случай использования должен этот трапецоид как-то иначе обрабатывать? Enum тут лучше, потому что компилятор покажет конкретные места где разные фигуры обрабатываются по-разному и реализация этих вариаций будет проводиться в контексте конкретной задачи.

khrundel ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.