Попробуйте преобразовать id_eval
в строку, подобную этой.
type Props = {
};
type State = {
id_evaluation: string,
};
class Evaluation extends Component < Props, State > {
state = {
id_evaluation: '1',
}
componentDidMount() {
const id_eval = getEvaluation();
this.setState({
id_evaluation: String(id_eval) || '',
});
Это нарушает инкапсуляцию. Вы не должны быть в состоянии обойти поведение родительского класса. Имеет смысл иногда быть в состоянии обойти Ваш собственный поведение класса (особенно из того же метода), но не Ваш родитель. Например, предположите, что у нас есть основной "набор объектов", подкласс, представляющий "набор красных объектов" и подкласса того представления "набора больших красных объектов". Имеет смысл иметь:
public class Items
{
public void add(Item item) { ... }
}
public class RedItems extends Items
{
@Override
public void add(Item item)
{
if (!item.isRed())
{
throw new NotRedItemException();
}
super.add(item);
}
}
public class BigRedItems extends RedItems
{
@Override
public void add(Item item)
{
if (!item.isBig())
{
throw new NotBigItemException();
}
super.add(item);
}
}
Это прекрасно - RedItems может всегда быть уверен, что объекты, которые он содержит, являются полностью красными. Теперь предположите, что мы были способны назвать super.super.add ():
public class NaughtyItems extends RedItems
{
@Override
public void add(Item item)
{
// I don't care if it's red or not. Take that, RedItems!
super.super.add(item);
}
}
Теперь мы могли добавить, что мы любим, и инвариант в RedItems
повреждается.
, который имеет смысл?
В предположении, потому что это не используется настолько часто. Единственная причина я видел использование его, состоит в том, если Ваш прямой родитель переопределил некоторую функциональность, и Вы пытаетесь восстановить его назад к оригиналу.
, Который, кажется, мне против принципов OO, так как прямой родитель класса должен быть более тесно связан с Вашим классом, чем прародитель.
Я думаю, перезаписываете ли Вы метод и хотите ко всей версии суперкласса ее (как, говорите для equals
), тогда Вы фактически всегда хотите назвать прямую версию суперкласса сначала, которую назовет своей версией суперкласса в свою очередь, если она хочет.
я думаю, что это только редко имеет смысл (если вообще. я не могу думать о случае, где он делает) назвать версию некоторого произвольного суперкласса метода. Я не знаю, возможно ли это вообще в Java. Это может быть сделано в C++:
this->ReallyTheBase::foo();
В дополнение к правильным замечаниям, которые сделали другие, я думаю, что существует другая причина: что, если суперкласс не имеет суперкласса?
, Так как каждый класс естественно расширяется (по крайней мере) Object
, super.whatever()
будут всегда обращаться к методу в суперклассе. Но что, если бы Ваш класс только расширяет Object
- к чему super.super
относился бы тогда? Как то поведение должно быть обработано - ошибка компилятора, NullPointer, и т.д.?
я думаю основная причина, почему это не позволяется, то, что она нарушает инкапсуляцию, но это могло бы быть небольшой причиной также.
У меня нет достаточной репутации для комментария, таким образом, я добавлю это к другим ответам.
Jon Skeet отвечает превосходно с красивым примером. Матовый B имеет точку: не все суперклассы имеют ужины. Ваш код повредился бы при вызове супер из супер, которое имело не супер.
Объектно-ориентированное программирование (который Java) является всем об объектах, не функциях. Если Вы хотите ориентированное программирование задачи, выберите C ++ или что-то еще. Если Ваш объект не вписывается, это - суперкласс, то необходимо добавить его к "классу прародителя", создать новый класс или найти другого супер, это действительно вписывается.
Лично, я нашел, что это ограничение одни из самых больших преимуществ Java. Код несколько тверд по сравнению с другими языками, которые я использовал, но я всегда знаю, что ожидать. Это помогает с "простой и знакомой" целью Java. В моем уме, звоня super.super не просто или знаком. Возможно, разработчики чувствовали то же?
Я думаю, что у Jon Skeet есть корректный ответ. Я был бы точно так же, как, чтобы добавить, что Вы можете доступ затененные переменные от суперклассов суперклассов путем кастинга this
:
interface I { int x = 0; }
class T1 implements I { int x = 1; }
class T2 extends T1 { int x = 2; }
class T3 extends T2 {
int x = 3;
void test() {
System.out.println("x=\t\t" + x);
System.out.println("super.x=\t\t" + super.x);
System.out.println("((T2)this).x=\t" + ((T2)this).x);
System.out.println("((T1)this).x=\t" + ((T1)this).x);
System.out.println("((I)this).x=\t" + ((I)this).x);
}
}
class Test {
public static void main(String[] args) {
new T3().test();
}
}
, который производит вывод:
x= 3 super.x= 2 ((T2)this).x= 2 ((T1)this).x= 1 ((I)this).x= 0
(пример от JLS)
Однако это не работает на вызовы метода, потому что вызовы метода определяются на основе типа выполнения объекта.
Похоже, возможно получить хотя бы класс суперкласса суперкласса, хотя и не обязательно его экземпляр, используя отражение; если это может быть полезно, рассмотрите Javadoc по адресу http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass ()
Я думаю, что следующий код позволяет использовать super.super ... super.method () в большинстве случаев. (даже если это уродливо делать)
Короче
Использование:
public class A {
public void doThat() { ... }
}
public class B extends A {
public void doThat() { /* don't call super.doThat() */ }
}
public class C extends B {
public void doThat() {
Magic.exec(A.class, this, "doThat");
}
}
public class Magic {
public static <Type, ChieldType extends Type> void exec(Class<Type> oneSuperType, ChieldType instance,
String methodOfParentToExec) {
try {
Type type = oneSuperType.newInstance();
shareVars(oneSuperType, instance, type);
oneSuperType.getMethod(methodOfParentToExec).invoke(type);
shareVars(oneSuperType, type, instance);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static <Type, SourceType extends Type, TargetType extends Type> void shareVars(Class<Type> clazz,
SourceType source, TargetType target) throws IllegalArgumentException, IllegalAccessException {
Class<?> loop = clazz;
do {
for (Field f : loop.getDeclaredFields()) {
if (!f.isAccessible()) {
f.setAccessible(true);
}
f.set(target, f.get(source));
}
loop = loop.getSuperclass();
} while (loop != Object.class);
}
}
Есть несколько веских причин сделать это. У вас может быть подкласс, у которого есть метод, реализованный неправильно, но родительский метод реализован правильно. Поскольку он принадлежит сторонней библиотеке, вы не можете/не хотите менять источник. В этом случае вы хотите создать подкласс, но переопределить один метод для вызова метода super.super.
Как показали некоторые другие постеры, это можно сделать через отражение, но должно быть возможно сделать что-то вроде
(SuperSuperClass this).theMethod();
Я сейчас занимаюсь этой проблемой - быстрое решение заключается в копировании и вставке метода суперкласса в метод подкласса :)