Подтвердить что ты не робот

Может ли java вызвать родительский переопределенный метод в других объектах, но не подтип?

здесь работает код Java

class Cup {
    public String sayColor() {
        return "i have a color .";
    }
}

class TCup extends Cup{
    public String sayColor(){
        System.out.println(super.getClass().getName());
        return super.sayColor()+"color is tee green.";
    }
}

class MyTCup extends TCup {
    public String sayColor(){
        System.out.println(super.getClass().getName());
        return super.sayColor()+"but brushed to red now!";
    }
}
class Test {
    public static void main(String[] args) {
        Cup c = new MyTCup();
        System.out.print(c.sayColor());
    }
}

и запуск тестовых отпечатков класса

MyTCup
MyTCup
i have a color .color is tee green.but brushed to red now!

вопрос 1: во время выполнения тип объекта C - это MyTCup, но он всегда может вызвать метод super. Существует ли стек методов в памяти внутри MyTCup после инициализации объекта, а затем может вызываться во время выполнения, как код?

вопрос 2: нет способа вызвать метод super в других объектах. Как я знаю, c++ может привести к вызову родительского метода в любое время. Почему это отличается в Java?

4b9b3361

Ответ 1

Вы не можете вызвать метод super в других объектах - это будет нарушать инкапсуляцию. Все дело в том, что объект контролирует то, что делают его переопределенные методы. Например, вы можете переопределить метод коллекции add для исключения исключения в определенных обстоятельствах, чтобы он мог обеспечить добавление только "действительных" элементов в коллекцию. Это было бы бессмысленно, если бы вызывающие могли просто обойти его с помощью актера!

Единственная причина, по которой объект получает вызов super.foo() для себя, - это включить один вызов, который будет реализован с использованием родительской реализации. Это до кода в классе, чтобы убедиться, что это только когда-либо делает это разумно. Опять же, чтобы взять пример надстройки в коллекции, если коллекция переопределяет add, он должен будет каким-то образом добавить проверенный элемент в коллекцию, что он будет делать с super.add().

Обратите внимание, что по той же причине, что и для инкапсуляции, вы можете вызывать только родительскую реализацию, а не реализацию grandparent - поэтому super.foo() действителен, но super.super.foo() нет.

Ответ 2

1

Ваш вопрос не совсем ясен. Что вы подразумеваете под "вызовом во время выполнения, например, с кодом"? Если вы спрашиваете, как экземпляр c знает, что такое его суперкласс, то да, иерархия классов хранится в памяти и может быть доступна VM.

2:

На самом деле Java позволяет вам передать экземпляр родительскому объекту. Просто при вызове метода в экземпляре всегда используется фактический класс экземпляра, а не его класс времени компиляции. То есть в Java все методы - это то, что будет называться "virtual" в С++. Почему это было решено, я не знаю.

Изменить: на самом деле Джон Скит прекрасно объясняет, почему вы не можете вызвать метод суперкласса на экземпляре подкласса, поэтому теперь я знаю: -).

Ответ 3

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

Ответ 4

На самом деле вы можете, но вам нужно использовать методологию, поэтому она будет работать только с вашим кодом.
В суперклассе добавьте параметр "Класс" к методу, например, в:

public String sayColor(Class classFilter){...

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

if(TCup.class!=classFilter)return super.sayColor(classFilter);
return "some text for TCup only";

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