Как подклассы класса 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 имеет только несколько полей, просто скопируйте и вставьте код.