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

StackOverflow https://stackoverflow.com/questions/1032847

  •  06-07-2019
  •  | 
  •  

Вопрос

вот рабочий 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:Нет никакого способа вызвать суперметод в других объектах.Насколько я знаю, c ++ может привести к вызову родительского метода в любое время.Почему в Java все по-другому?

Это было полезно?

Решение

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

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

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

Другие советы

1:

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

2:

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

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

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

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

public String sayColor(Class classFilter){...

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top