В чем проблема хрупкого базового класса? - PullRequest
23 голосов
/ 27 мая 2010

В чем проблема хрупкого базового класса в Java?

Ответы [ 3 ]

24 голосов
/ 27 мая 2010

Хрупкий базовый класс - распространенная проблема с наследованием, которая применяется к Java и любому другому языку, поддерживающему наследование.

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

Есть несколько способов смягчить это; но нет простого способа полностью избежать этого, все еще используя наследование. Вы можете предотвратить наследование других классов от класса, пометив объявление класса как final в Java.

Лучшая практика, позволяющая избежать худших из этих проблем, - помечать все классы как окончательные, если вы специально не собираетесь наследовать от них. Для тех, кто намеревается унаследовать, разработайте их так, как если бы вы проектировали API: скрыли все детали реализации; будьте строгими в отношении того, что вы излучаете, и внимательно относитесь к тому, что вы принимаете, и подробно документируйте ожидаемое поведение класса.

12 голосов
/ 27 мая 2010

Базовый класс называется хрупким, когда внесенные в него изменения нарушают производный класс.

class Base{
    protected int x;
    protected void m(){
       x++;
    }

    protected void n(){
      x++;      // <- defect 
      m();
     }
 }


class Sub extends Base{
        protected void m(){
            n();
        }
    }
0 голосов
/ 31 января 2017

Все, что сказал «Колин Пикард», является правдой, и здесь я хочу добавить некоторые из лучших практик, чтобы быть более защищенными, когда вы пишете код, который может вызвать проблемы такого рода на языке Java, и особенно если вы создание фреймворка или библиотеки ...

  1. Сделайте все ваши конкретные классы окончательными по умолчанию, потому что вы можете не захотеть, чтобы они были унаследованы Вы обнаружили, что этот тип поведения включает в себя множество языков, таких как язык Kotlin (если вам нужно расширить его, тогда удалите ключевое слово final, чтобы оно могло помочь читателю вашего кода).
  2. Для абстрактных классов, сделайте так, чтобы все его реализованные методы были окончательными, чтобы их подклассы не модифицировались (вообще говоря, даже защищенные методы - плохая идея, подклассы не должны так много знать о своих подклассах), не раскрывайте ваш метод, если они не предназначено для переопределения ...
  3. Старайтесь не использовать RatioShip [is], вместо этого попробуйте использовать [использует a] отношения между вашими диаграммами классов, используйте интерфейсы, чтобы избежать проблем с расширениями.
  4. Помните, что каждое расширение может быть заменено на орудия, и если вам нужно сделать реализацию по умолчанию, вот код спине:

public interface MyBehavior {
    void doAction();

    static class Implementation implements MyBehavior {
        public void doAction() {
            //do some stuff
        }
    }
}

//  instead of doing extends To a class that have the doAction method
//  we will make a [use a] relationShip between the Example class & the Implementation class
public class Example {
    private MyBehavior.Implementation helper = new MyBehavior.Implementation();

    public void doAction() {
        this.helper.doAction();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...