Действительно ли возможно скрыть или понизить доступ к Унаследованным методам в Java?

Эта статья является хорошей для шаблона состояния (хотя это - C++, не конкретно C).

, Если можно поместить руки на книгу" Главные Первые Шаблоны разработки ", объяснение и пример являются очень четкими.

14
задан Daniel Bingham 14 December 2009 в 18:32
поделиться

7 ответов

Я думаю, что сама природа проблемы в том виде, в котором вы ее поставили, выявляет концептуальные проблемы с вашей объектной моделью. Вы пытаетесь описать различные отдельные обязанности как отношения «есть», в то время как на самом деле то, что вы должны делать, описывает отношения «имеет» или «использует». Сам факт того, что вы хотите скрыть функциональность базового класса от дочернего класса, говорит мне, что эта проблема на самом деле не отображается на трехуровневом дереве наследования.

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

Вы сказали:

Основа class - это базовый класс таблицы управление частью обработки базы данных Это. Есть изрядное количество содержащаяся в нем функциональность, которая общий для всех типов таблиц - как раз они в базе данных они становятся uniform.

Это могло бы быть более ясным, но похоже, что у нас есть один класс, который должен управлять соединением с БД и общими операциями с БД. После Single Responsibility , я думаю, мы на этом закончили. Вам не нужно расширять этот класс, вам нужно передать его классу, который должен использовать его функциональные возможности.

Средний класс характерен для вид таблицы в файле проанализирован, и есть анализ таблицы и логика импорта. Ему нужен доступ к некоторым доступа к базе данных базового класса функции.

«Средний класс» здесь звучит немного как Data Mapper . Этому классу не нужно расширять предыдущий класс, ему нужна ссылка на него, возможно, введенная в конструктор или установщик в качестве интерфейса.

Класс верхнего уровня специфичен для стол и не делает ничего, кроме инициализировать макет таблицы способом родительские классы могут понять. Также пользователи базового класса не нужно увидеть или получить доступ к базе данных конкретные функции, которые в середине класс делать. По сути, я хочу раскрыть эти функции только на одном уровне выше базового класса и никого другого.

Я не понимаю, почему высокоуровневый класс, кажется, знает схему db (по крайней мере, это то, что мне подсказывает фраза «инициализировать макет таблицы»), но опять же, если бы отношения между первыми двумя классами были инкапсуляцией ("имеет" / "использует") вместо наследования ("является") , я не думаю, что это было бы проблемой.

17
ответ дан 1 December 2019 в 06:18
поделиться

Нет. Я не уверен, почему вы цитируете спецификацию, а затем спрашиваете, есть ли способ сделать противоположное тому, что сказано в спецификации ...

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

10
ответ дан 1 December 2019 в 06:18
поделиться

При переопределении метода вы можете сделать его только общедоступным , а не более частным. Я не знаю, почему вы используете слово «общий»

. Помните, что в порядке от наименее ограничительного к наиболее строгому:

public<protected<default<private

Да, « защищенный » является модификатором доступа с меньшими ограничениями, чем default (когда модификатор не используется), поэтому вы можете переопределить метод по умолчанию, пометив метод переопределения как protected , но не делать наоборот.

Банка: Вы можете заменить защищенный метод на открытый метод.

Невозможно: Вы не можете заменить общедоступный метод на защищенный метод.

6
ответ дан 1 December 2019 в 06:18
поделиться

Если бы вы сделали это, то DerivedOne не был бы Базой с точки зрения DerivedTwo. Вместо этого вам нужен класс-оболочка

//Uses myMethod but keeps it hidden
public class HiddenBase {
    private final Base base = new Base();
    private void myMethod();
    public void otherMethod() {base.otherMethod();}
}

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

6
ответ дан 1 December 2019 в 06:18
поделиться

Наследование работает, потому что везде, где вы можете использовать базовый класс, вы также можете использовать один из его подклассов. Поведение может быть другим, но API - нет. Эта концепция известна как принцип подстановки Лискова .

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

То, что вы действительно хотите сделать, можно сделать с помощью интерфейсов:

interface IBase1 {
}

class Derived1 implements IBase1 {
  public void myMethod() {
  }
}

class Derived2 implements IBase1 {
}

class UseMe {
  public void foo(IBase1 something) {
     // Can take both Derived1 and Derived2
     // Can not call something.myMethod()
  }
  public void foo(Derived1 something) {
     something.myMethod();
  }
  public void foo(Derived2 something) {
    // not something.myMethod()
  }
}
3
ответ дан 1 December 2019 в 06:18
поделиться

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

рассмотрите следующее:


package a;

public class Base {
    void myMethod() {
        System.out.println("a");
    }
}

package a;

public class DerivedOne extends Base {
    @Override
    void myMethod() {
        System.out.println("b");
    }
}

package b;

public class DerivedTwo extends a.DerivedOne {
    public static void main(String... args) {
        myMethod(); // this does not compile...
    }
}

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

3
ответ дан 1 December 2019 в 06:18
поделиться

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

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

// Uses myMethod and then hides it.
public class DerivedOne extends Base {
    @Override
    public void myMethod() {
        throw new IllegalStateException("Illegal access to myMethod");
    }

    private void myPrivateMethod() {
        super.myMethod();
    }

}

Edit : чтобы ответить на вашу разработку , если я правильно вас понял, вам нужно указать поведение в контексте базового класса, который определен в среднем классе. Абстрактные защищенные методы не будут невидимы для классов, производных от среднего класса.

Один из возможных подходов состоит в том, чтобы определить интерфейс с методами, которые должны быть абстрактными в базовом классе, сохранение частной окончательной ссылки в базовом классе и предоставление ссылки на реализацию при создании объектов среднего класса.

Интерфейс будет реализован в виде (статического?) Вложенного внутри среднего класса. То, что я имею в виду, выглядит так:

public interface Specific {
    public void doSomething();
}

public class Base {
    private final Specific specificImpl;

    protected Base(Specific s) {
        specificImpl = s;
    }

    public void doAlot() {

         // ...

         specificImpl.doSomething();

         // ...
    }
}

public class Middle extends Base {

    public Middle() {
        super(new Impl());
    }

    private Impl implements Specific {

        public void doSomething() {

            System.out.println("something done");
        }
    }
}

public class Derived extends Middle {

    // Access to doAlot()
    // No access to doSomething()
}
3
ответ дан 1 December 2019 в 06:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: