Я прочитал этот вопрос и подумал, что его легко решить (а не без него), если бы можно было написать:
@Override
public String toString() {
return super.super.toString();
}
Я не уверен, что это полезно во многих случаях, но мне интересно, почему это не так, и если что-то подобное существует на других языках.
Что вы думаете, ребята?
РЕДАКТИРОВАТЬ: Чтобы уточнить: да, я знаю, это невозможно в Java, и я действительно не скучаю по этому. Это ничего, что я ожидал работать и был удивлен, получив ошибку компилятора. У меня просто была идея, и я хотел бы обсудить это.
java
superclass
Тим Бюте
источник
источник
super.super.toString()
противоречит вашему собственному решению, когда вы решаете расширить класс, принимая все (а не некоторые) его функции.Ответы:
Это нарушает инкапсуляцию. Вы не должны быть в состоянии обойти поведение родительского класса. Иногда имеет смысл обходить поведение вашего собственного класса (особенно в рамках одного и того же метода), но не поведения ваших родителей. Например, предположим, что у нас есть базовая «коллекция предметов», подкласс, представляющий «коллекцию красных предметов», и подкласс этого класса, представляющий «коллекцию больших красных предметов». Имеет смысл иметь:
Это нормально - RedItems всегда может быть уверен, что все содержащиеся в нем элементы имеют красный цвет. Теперь предположим , что мы были в состоянии назвать super.super.add ():
Теперь мы можем добавить все, что захотим, и инвариант не
RedItems
работает.Имеет ли это смысл?
источник
Я думаю, что у Джона Скита правильный ответ. Я просто хотел бы добавить, что вы можете получить доступ к теневым переменным из суперклассов суперклассов, приведя
this
:который производит вывод:
(пример из JLS )
Однако это не работает для вызовов методов, потому что вызовы методов определяются на основе типа времени выполнения объекта.
источник
Я думаю, что следующий код позволяет использовать super.super ... super.method () в большинстве случаев. (даже если это некрасиво)
Короче говоря
Применение :
источник
super.super.
предлагает программистам находить новые, запутанные и вопиющие способы выстрелить себе в ногу в поисках обходного пути, это прекрасный пример этого, потому что ваши коллеги, вероятно, будут ненавидеть вас за то, что вы что-то пишете вот так, что они лично и буквально застрелят тебя в ногу. +1У меня недостаточно репутации, чтобы комментировать, поэтому я добавлю это к другим ответам.
Джон Скит отвечает превосходно, с прекрасным примером. У Мэтта B есть пункт: не у всех суперклассов есть супер. Ваш код сломался бы, если бы вы назвали супер супер, у которого не было супер.
Объектно-ориентированное программирование (то есть Java) - это все об объектах, а не функциях. Если вы хотите программирование, ориентированное на задачи, выберите C ++ или что-то еще. Если ваш объект не вписывается в его суперкласс, вам нужно добавить его в «класс прародителя», создать новый класс или найти другой суперкласс, в который он вписывается.
Лично я обнаружил, что это ограничение - одна из самых сильных сторон Java. Код несколько жесткий по сравнению с другими языками, которые я использовал, но я всегда знаю, чего ожидать. Это помогает с «простой и знакомой» целью Java. На мой взгляд, назвать super.super не просто и не привычно. Возможно, разработчики чувствовали то же самое?
источник
Есть несколько веских причин для этого. У вас может быть подкласс, у которого есть метод, который реализован неправильно, но родительский метод реализован правильно. Поскольку она принадлежит сторонней библиотеке, вы не можете / не хотите менять источник. В этом случае вы хотите создать подкласс, но переопределить один метод для вызова метода super.super.
Как показали некоторые другие плакаты, это можно сделать с помощью размышлений, но должно быть возможно сделать что-то вроде
(SuperSuperClass this) .theMethod ();
Я имею дело с этой проблемой прямо сейчас - быстрое решение состоит в том, чтобы скопировать и вставить метод суперкласса в метод подкласса :)
источник
В дополнение к очень хорошим замечаниям других, я думаю, есть еще одна причина: что, если у суперкласса нет суперкласса?
Поскольку каждый класс естественным образом расширяется (по крайней мере)
Object
,super.whatever()
он всегда будет ссылаться на метод в суперклассе. Но что, если ваш класс только расширяетсяObject
- что будетsuper.super
означать тогда? Как следует обрабатывать такое поведение - ошибка компилятора, NullPointer и т. Д.?Я думаю, что основная причина, почему это не разрешено, заключается в том, что это нарушает инкапсуляцию, но это также может быть небольшой причиной.
источник
Я думаю, что если вы переписываете метод и хотите использовать все его версии суперкласса (например, для
equals
), то вам практически всегда нужно сначала вызывать прямую версию суперкласса, которая, в свою очередь, будет вызывать его версию суперкласса. ,Я думаю, что редко имеет смысл (если вообще. Я не могу придумать случай, когда это происходит) вызывать версию метода произвольного суперкласса. Я не знаю, возможно ли это вообще на Java. Это можно сделать в C ++:
источник
На предположение, потому что это не так часто используется. Единственная причина, по которой я мог его использовать, заключается в том, что ваш прямой родитель переопределил некоторые функции, и вы пытаетесь восстановить его обратно к исходному.
Мне кажется, что это противоречит принципам ОО, поскольку непосредственный родительский класс должен быть более тесно связан с вашим классом, чем дедушка и дедушка.
источник
Посмотрите на этот проект Github, особенно на переменную objectHandle. Этот проект показывает, как на самом деле и точно вызвать метод дедушки и дедушки для внука.
На случай, если ссылка не работает, вот код:
Удачного кодирования !!!!
источник
Я бы поместил тело метода super.super в другой метод, если это возможно
Или, если вы не можете изменить супер-супер класс, вы можете попробовать это:
В обоих случаях
Результаты "Я супер супер"
источник
Казалось бы, возможно, по крайней мере, получить класс суперкласса суперкласса, хотя не обязательно его экземпляр, используя отражение; если это может быть полезно, рассмотрите Javadoc на http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass ()
источник
запустить: СТРОИТЬ УСПЕШНО (общее время: 0 секунд)
источник
Вызов super.super.method () имеет смысл, когда вы не можете изменить код базового класса. Это часто происходит, когда вы расширяете существующую библиотеку.
Спросите себя сначала, почему вы расширяете этот класс? Если ответ «потому что я не могу его изменить», то вы можете создать точный пакет и класс в своем приложении и переписать непослушный метод или создать делегат:
Например, вы можете создать org.springframework.test.context.junit4.SpringJUnit4ClassRunner класс в вашем приложении, так что этот класс должен быть загружен до реального из jar. Затем перепишите методы или конструкторы.
Внимание: это абсолютный взлом, и его крайне НЕ рекомендуется использовать, но он РАБОТАЕТ! Использование этого подхода опасно из-за возможных проблем с загрузчиками классов. Также это может вызывать проблемы при каждом обновлении библиотеки, содержащей перезаписанный класс.
источник
У меня были ситуации, подобные этим, когда архитектура заключается в построении общей функциональности в общем CustomBaseClass, который реализует от имени нескольких производных классов. Однако нам нужно обойти общую логику для конкретного метода для определенного производного класса. В таких случаях мы должны использовать реализацию super.super.methodX.
Мы достигаем этого, вводя логический член в CustomBaseClass, который может использоваться для выборочной отсрочки пользовательской реализации и при желании уступить реализации фреймворка по умолчанию.
Тем не менее, при соблюдении хороших принципов архитектуры, применяемых как в среде, так и в приложении, мы могли бы легко избежать таких ситуаций, используя подход hasA вместо подхода isA. Но во все времена не очень практично ожидать хорошо спроектированную архитектуру на месте, и, следовательно, отойти от прочных принципов проектирования и внедрять подобные хаки. Просто мои 2 цента ...
источник
@ Джон Скит Хорошее объяснение. IMO, если кто-то хочет вызвать метод super.super, тогда нужно хотеть игнорировать поведение непосредственного родителя, но хотеть получить доступ к поведению великого родителя. Это может быть достигнуто с помощью. Как ниже код
Вот класс водителя,
Выход этого будет
В этом случае поведение printClass класса B будет игнорироваться. Я не уверен, является ли это идеальной или хорошей практикой для достижения super.super, но все же это работает.
источник
Если вы думаете, что вам понадобится суперкласс, вы можете ссылаться на него в переменной для этого класса. Например:
Следует распечатать:
источник
new UltraFoo.getNumber()
не буду компилировать, так как вы пропустили круглые скобки. Тем не менее, я только что удалил свой donvote, так как концепция вашего кода теперь достаточно ясна, спасибо!ИМО, это чистый способ достижения
super.super.sayYourName()
поведения в Java.Вывод:
Request to lie: d.sayYourName(true) returns Grandma Fedora
Request not to lie: d.sayYourName(false) returns Little girl Masha
источник
Я думаю, что это проблема, которая нарушает соглашение о наследовании.
Расширяя класс, вы подчиняетесь / соглашаетесь с его поведением, функциями.
При вызове
super.super.method()
вы хотите разорвать собственное соглашение о послушании.Вы просто не можете выбрать вишню из супер класса .
Однако могут возникнуть ситуации, когда вы чувствуете необходимость вызова
super.super.method()
- обычно это плохой знак дизайна, в вашем коде или в коде, который вы наследуете!Если супер и супер супер классы не могут быть реорганизованы (некоторый унаследованный код), тогда выбирайте композицию вместо наследования. Нарушение
инкапсуляции - это когда вы переопределяете некоторые методы, нарушая инкапсулированный код. Методы, разработанные так, чтобы их нельзя было переопределить, помечаются как окончательные .
источник
В C # вы можете вызвать метод любого предка, как это:
Также вы можете сделать это в Delphi:
Но в Java вы можете сделать такой фокус только с помощью некоторого механизма. Один из возможных способов:
Результат результата objC.DoIt ():
источник
Это просто легко сделать. Например:
C подкласс B и B подкласс A. Например, оба из трех имеют метод methodName ().
Выполнить класс C Выходные данные будут: Класс A Класс C
Вместо вывода: класс A, класс B, класс C
источник
Вывод: напечатано в дедуля
источник
super.super.method()
недопустимый код в Java.Ключевое слово super - это просто способ вызова метода в суперклассе. В руководстве по Java: https://docs.oracle.com/javase/tutorial/java/IandI/super.html
Если ваш метод переопределяет один из методов его суперкласса, вы можете вызвать переопределенный метод с помощью ключевого слова super.
Не верьте, что это ссылка на супер объект !!! Нет, это просто ключевое слово для вызова методов в суперклассе.
Вот пример:
Когда вы вызываете
cat.doSth()
, методdoSth()
в классеAnimal
будет печатать,this
и это кошка.источник