Частный доступ с самоограниченными генериками - PullRequest
3 голосов
/ 03 сентября 2011

Комбинация доступа к частному полю с CRTP в Java кажется странным крайним случаем в правилах видимости:

public abstract class Test<O extends Test<O>> implements Cloneable {
    private int x = 0;

    @SuppressWarnings("unchecked")
    @Override
    protected final O clone() {
        try {
            return (O) super.clone();
        } catch (CloneNotSupportedException ex) {
            throw new AssertionError(ex);
        }
    }

    public final int getX() {
        return x;
    }

    public final O withX(int x) {
        O created = clone();
        created.x = x;  // Compiler error: The field Test<O>.x is not visible
        return created;
    }
}

Просто изменив метод withX() на этот ...

    public final O withX(int x) {
        O created = clone();
        Test<O> temp = created;
        temp.x = x;
        return created;
    }

... делает код компилируемым.Я проверил это в Oracle javac и в компиляторе Eclipse.Что дает?

1 Ответ

7 голосов
/ 03 сентября 2011

Это на самом деле не проблема с генериками. Правила наследования JLS не позволяют отображать закрытые поля в подклассах. Поскольку X является закрытым, он не является членом типа O, даже если он является членом типа Test<O>, а O является подтипом Test<O>. Если вы использовали код как:

public final O withX(int x) {
    Test<O> created = clone();
    created.x = x;
    return (O) created;
}

Это будет работать. Это случай, когда LSP не поддерживается Java, но это только локальная проблема с системой типов, поскольку частные поля доступны только для объектов того же типа. Если бы это не сработало, тогда частные поля не были бы частными. Я не думаю, что иметь специальное исключение из правил для рекурсивных шаблонов - это хорошая идея.

Обратите внимание, это никогда не является ограничением того, что вы можете сделать. Вы всегда можете преобразовать подтип до супертипа, когда хотите внести изменения, как в альтернативном коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...