Как подклассы класса AutoValue?
Я использую расширение AutoValue для создания классов Parcelable Android. В документации конкретно указано, что один @AutoValue не может расширять другой: https://github.com/google/auto/blob/master/value/userguide/howto.md#inherit
Другой разработчик помог мне в этом и предложил "Если у вас есть общие поля, вы можете поместить их в интерфейс, который реализуются обе реализации". Я предполагаю, что это означает, что библиотека поддерживает композицию над наследованием.
Я признаю, что я потерял. Если бы кто-то мог предоставить простой конкретный пример простейшего способа "подкласса" класса AutoValue, это было бы оценено. Здесь простой класс:
@AutoParcelGson
public abstract class User implements Parcelable {
public abstract String username();
public static User create(String username) {
return builder().username(username).build();
}
public static Builder builder() {
return new AutoParcelGson_User.Builder();
}
@AutoParcelGson.Builder
public interface Builder {
Builder username(String username);
User build();
}
}
Я хотел бы иметь еще один класс @AutoValue, называемый Customer, который имеет несколько дополнительных полей. Кроме того, @AutoParcelGson является расширением @AutoValue, которое я использую, но это то же поведение.
Ответы
Ответ 1
Документация AutoValue гласит: "Эта возможность намеренно не поддерживается, потому что нет способа сделать это правильно. См. "Эффективная Java", 2-е издание, пункт 8: "Соблюдайте общий контракт, когда переопределение равно". "Хорошая книга, я многому научился. В 3-м издании, пункт 10. Короче говоря: допустим, вы расширяете свой класс User
на BetterUser
. BetterUser betterUser.equals(User user)
может быть верным в некоторых случаях, но в этих случаях user.equals(betterUser)
не определено. Симметрия нарушена. И это только одна из проблем; чем больше вы пытаетесь, тем хуже становится. Кстати, это не специфично для классов AutoValue, но является общей проблемой наследования.
Единственное согласованное решение - создание нового класса BetterUser
, который не расширяет User
, но имеет поле типа User
. Таким образом, вы можете определять поведение BetterUser
, как вам нравится, без какого-либо влияния на другие классы. Или, может быть, если User
имеет только несколько полей, просто скопируйте и вставьте код.