Как обойти наследование в Java при вызове метода - PullRequest
1 голос
/ 04 февраля 2009
    class Super {

        public void anotherMethod(String s) {
            retValue(s)
        }


        public String retValue(String s) {
            return "Super " + s;
        }

    }

    class Sub extends Super {

        public void anotherMethod(String s) {
            retValue(s)
        }

        public String retValue(String s) {
            return "Sub " + s;
        }

    }

если предположить в основном,

Super s = new Sub();
s.anotherMethod("Test");

Вывод будет, суб тест

Можете ли вы помочь мне рассказать, как получить вывод Супер тест с указанными последовательностями в основном .

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

Ответы [ 10 ]

10 голосов
/ 04 февраля 2009

Зачем вам это нужно ??

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

7 голосов
/ 04 февраля 2009

Всякий раз, когда я задаю (или задаю) вопрос, подобный этому, я категорически знаю , что я допустил ошибку в своем дизайне и / или моих определениях объектов. Вернитесь к иерархии объектов и проверьте, перепроверьте и перепроверьте, что каждое отношение наследования представляет собой «IS-A», а не «HAS-A» или что-то еще более слабое.

3 голосов
/ 04 февраля 2009

И позвольте мне объяснить, почему я этого хочу, скажем, у меня есть класс, который имеет метод test () и он может быть переопределен подклассы, в некоторых случаях я хочу переопределить тест () и в некоторых случаях test () самого суперкласса, там Есть много способов сделать это, это будет полезно, если кто-то может быть лучшим решение.

Если ваш подкласс переопределяет test(), , то он переопределяет test () - в этом весь смысл наследования объекта. Вы просто вызываете методы объекта, которые динамически разрешаются в соответствующую реализацию на основе класса времени выполнения объекта. В этом и заключается прелесть полиморфной типизации, фактически вызывающему не нужно вообще ничего об этом знать, а подклассы определяют, как их поведение отличается от суперкласса.

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

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

Какой из них вы выберете, концептуально зависит от того, будет ли ваш main метод (т.е. вызывающий объект) или сами объекты (под) класса находиться в наилучшем положении, чтобы определить, следует ли вызывать метод суперкласса или нет.

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

2 голосов
/ 04 февраля 2009

Вам нужно будет пройти маршрут:

Super s = new Super();
s.anotherMethod("Test");

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

class Sub extends Super {

    public String anotherMethod( String s, boolean bSuper ) {
        if( bSuper )
            return super.retValue(s);
        else
            return retValue(s);
    }

    public String retValue(String s) {
        return "Sub " + s;
    }

}
0 голосов
/ 04 февраля 2009

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

Super sub = new Sub() {
  @Override
  public String retValue() {
    // re-implement Super.retValue()
  }
};
otherObject.use(sub);

Конечно, для этого необходимо, чтобы вы имели или могли воспроизводить исходный код Super.retValue () и чтобы этот метод не использовал то, к чему у вас нет доступа от анонимного ребенка. Если API плохо спроектирован, вам стоит подумать о том, чтобы заменить его на что-то другое.

0 голосов
/ 04 февраля 2009

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

Итак, изменив исходный пример:

class Super {<br>
        public static void staticMethod(String s) {
            System.out.println("Super " + s);
        }
}</p>

<pre><code>class Sub extends Super {

    public static void staticMethod(String s) {
        System.out.println("Sub " + s);
    }

}

public static void main(String[] args) {

    Super s = new Sub();
    s.staticMethod("Test");

}

тогда main () выведет «Super test».

Но все же не делайте этого , пока не поймете, почему вы хотите, и вы не поймете, что вводите подклассы, а затем безвозмездно работаете над тем, чтобы они там были. Например, большинство IDE помечают вышеприведенный пример множеством предупреждений, в которых говорится, что вам не следует вызывать статические методы для переменных экземпляра (т.е. предпочитайте Super.staticMethod("Test") вместо s.staticMethod("Test")), именно по этой причине.

0 голосов
/ 04 февраля 2009

Можете ли вы помочь мне рассказать, как чтобы получить вывод "Super Test" с данные последовательности в main.

  • Не перезаписывайте anotherMethod() и retValue() в Sub, во-первых.

  • В S ub.anotherMethod() вернуть super.retValue(s) вместо retValue(s).

0 голосов
/ 04 февраля 2009

Хотя я согласен с другими авторами в том, что это не лучшая идея в мире, я считаю, что это можно сделать с небольшим изменением.

Если ваш дочерний класс был определен как:

    class Sub extends Super {

        public void anotherMethod(String s) {
            retValue(s)
        }

        public void yetAnotherMethodString s) {
            super.retValue(s)
        }

        public String retValue(String s) {
            return "Sub " + s;
        }

    }

, а затем вызовите этот новый метод в своем главном, вы сможете распечатать "Super Test".

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

0 голосов
/ 04 февраля 2009

Тип выполнения s равен Sub, поэтому вы только когда-либо вызываете методы для этого класса.

0 голосов
/ 04 февраля 2009

Из класса Sub вы можете вызвать super.anotherMethod ("bla"), но вы не можете получить доступ к методу суперкласса в вашем основном методе - это противоречит самой идее использования подклассов.

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