Почему бы не сериализовать абстрактные классы в Java?
Я прочитал, что обычно абстрактные классы не должны быть Сериализуемы в Java. Подклассы должны быть сериализуемыми (с пользовательскими методами чтения, записи, если требуется, например. когда абстрактные классы имеют поля).
в чем причина этого? Почему это считается плохим дизайном?
обновление 1: у меня есть абстрактный класс с полями и три подкласса. На данный момент я использую следующий подход.
Я сделал все подклассы serializable с пользовательскими методами чтения, записи. В абстрактном классе у меня есть следующие методы.
void writeFields(ObjectOutputStream out)throws IOException { .... }
void readFields(ObjectInputStream in) throws IOException, ClassNotFoundException{ ... }
в пользовательском read, write методы в подклассах я вызываю эти методы для (de) сериализации полей в абстрактном классе. Правильный ли это подход? Или есть другой, лучший подход?
обновление 2:отражение, чтобы изменить окончательные поля, как посоветовал Джереми Мэнсон.
4 ответов
Я не знаю, что он обязательно плохой дизайн. Сериализация фактически является проблемой реализации (обратите внимание, что Джош блох не согласен со мной), поэтому не имеет смысла для интерфейсов. Если абстрактный класс имеет состояние, то вы хотели бы сделать его serialisable. Если у него нет состояния, нет никаких причин делать это так.
возьмем пример. java.security.cert.Certificate
- абстрактный сериализуемый класс с "type"
поле serialisable. Если бы не serialisable не будет возможно для подкласса быть сериализуемым и установить это поле. Тебя заставят взломать.
отметим, что java.io.Serializable
Хак. Это не должно было быть интерфейсом. Аннотация (или эволюция языка, например transient
) было бы более уместно.
как всегда, лучше предпочесть композицию наследованию и не делать случайный класс сериализуемым.
Я думаю, причина в том, что если абстрактный класс реализует сериализуемый, нет никакого способа сказать, что подтип не должен быть Сериализуемым. Лучше позволить каждому конкретному типу заявить о себе...
давайте займем позицию oposite. Если бы вы должны были де-сериализовать объект, каков был бы его тип?
по определению, абстрактный класс не может быть инстанцирован. Если вы можете сериализовать его, это означает, что он также может быть десериализован, и это даст вам экземпляр абстрактного класса. Это противоречит определению абстрактного класса и, следовательно, не может быть сделано.
Это только плохой дизайн, потому что это вынужденное решение, что, если вы хотите подкласс, который имеет несериализуемых членов.
вот почему.
например. Список не сериализуем, но каждая реализация основного списка. (Я знаю, что list-это интерфейс, но абстрактный класс без членов = / = интерфейс)