Остановка наследования без использования final - PullRequest
8 голосов
/ 16 января 2009

Есть ли другой способ остановить наследование класса, кроме объявления его как final или объявления его конструктора как частного?

Ответы [ 8 ]

29 голосов
/ 16 января 2009

Комментарий

//Do not inherit please
23 голосов
/ 16 января 2009

Еще два варианта:

  • сделать каждый метод окончательным, чтобы люди не могли их переопределить. Таким образом вы избегаете случайного вызова методов из подкласса. Это не останавливает подклассы.

  • поместите проверку в конструктор для класса:

    if (this.getClass() != MyClass.class) {
        throw new RuntimeException("Subclasses not allowed");
    }
    

    Тогда никто не сможет создать экземпляр подкласса вашего класса.

(Не то чтобы я предлагал использовать эти приемы, мне просто пришло в голову. Я бы использовал final class и / или private constructor)

8 голосов
/ 16 января 2009

Final был создан для решения этой проблемы.

7 голосов
/ 16 января 2009
  • Используйте окончательный
  • Использовать частные конструкторы
  • Используйте комментарий:

    // do not inherit
    
  • Используйте комментарий Javadoc

  • Сделайте все методы окончательными, чтобы люди не могли их переопределить
  • Использовать проверку во время выполнения в конструкторе класса:

    if (this.getClass() != MyClass.class) {
        throw new RuntimeException("Subclasses not allowed");
    }
    
4 голосов
/ 16 января 2009

Использование final является каноническим способом.

public final class FinalClass {
  // Class definition
}

Если вы хотите предотвратить переопределение отдельных методов, вы можете объявить их как final. (Я просто догадываюсь, почему вы хотели бы , чтобы избежать окончательного завершения всего класса.)

3 голосов
/ 17 января 2009

Сделайте ваши конструкторы частными и предоставьте фабричные функции для создания экземпляров.

Это может быть особенно полезно, когда вы хотите выбрать подходящую реализацию из нескольких, но не хотите разрешать произвольные подклассы, как в

abstract class Matrix {
   public static Matrix fromDoubleArray(double[][] elemens) {
     if (isSparse(elements)) {
      return new SparseMatrix(elements);
    } else {
      return new DenseMatrix(elements);
    }
  }
  private Matrix() { ... }  // Even though it's private, inner sub-classes can still use it
  private static class SparseMatrix extends Matrix { ... }
}
1 голос
/ 16 января 2009

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

0 голосов
/ 22 декабря 2017

Без использования финального класса вы можете сделать все конструкторы приватными:

public class A {
    private A() {} //Overriding default constructor of Java
}

Что, хотя и сделает этот класс абстрактным, запретив создание объекта этого класса, тем не менее, поскольку любое наследование требует super(); в конструкторе, и поскольку конструктор является закрытым, ошибка компиляции будет максимально возможной. получить, когда кто-то пытается унаследовать этот класс. Тем не менее, я бы рекомендовал использовать final вместо этого, так как он меньше кода и включает в себя возможность создания объектов.

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