Аргумент конструктора теряется при передаче суперконструктору

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

public abstract class AbstractFoo<T extends AbstractFoo> {
     protected T parent;

     protected AbstractFoo(T parent){
          if (parent != null) parent.addChild(this);
          this.parent = parent;
     }
     //...
}

public class Foo<T extends Foo> extends AbstractFoo<T> {
     public Foo(T parent){
          super(parent);
          //...
     }
}

public class SpecialFoo<T extends SpecialFoo> extends Foo<T> {
     public SpecialFoo(T parent){
          super(parent);
          //...
     }
}

Когда я передаю родительский аргумент конструктору SpecialFoo, конструктор Foo будет вызываться как суперконструктор, а этот конструктор, в свою очередь, вызывает конструктор AbstractFoo как суперконструктор.

У меня проблема в том, что родительский аргумент сбрасывается в NULL при передаче от Foo к AbstractFoo. Я понятия не имею, почему это происходит. Может ли кто-нибудь сказать мне, что мне нужно сделать, чтобы передать его абстрактному базовому классу целым и невредимым?


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

 public abstract class AbstractFoo<T extends AbstractFoo> {
      protected T parent;

      protected AbstractFoo(T parent){
           if (parent != null) parent.addChild(this);
           this.parent = parent;
      }
      //...
 }

 public class Foo<T extends Foo> extends AbstractFoo<T> {
      protected T parent;

      public Foo(T parent){
           super(parent);
           //...
      }
 }

 public class SpecialFoo<T extends SpecialFoo> extends Foo<T> {
      private SpecialFoo parent;

      public SpecialFoo(T parent){
           super(parent);
           //...
      }
 }

person dzirique    schedule 11.05.2012    source источник
comment
Мне кажется очень маловероятным. Покажите краткий, но полный пример, демонстрирующий проблему.   -  person Jon Skeet    schedule 11.05.2012


Ответы (2)


Вы проверили, что ваш родитель не null вы даете свой конструктор SpecialFoo?

person philnate    schedule 11.05.2012
comment
Когда я отлаживаю, родитель не имеет значения null в конструкторе SpecialFoo и в конструкторе Foo, но он действительно равен нулю в конструкторе AbstractFoo. - person dzirique; 11.05.2012
comment
Тогда, пожалуйста, попробуйте написать наименьший возможный пример, вызывающий проблему. Вы можете найти проблему самостоятельно, переплавляя свой код. - person philnate; 11.05.2012

Просмотрите эти пункты:

  1. Докажите ПОЛОЖИТЕЛЬНО, что вы получаете аргумент null в конструкторе (распечатайте его);
  2. Проверьте наличие других конструкторов в ваших классах. Возможно, вы вызываете конструктор, который не ожидаете вызывать, особенно из-за универсального типа этого аргумента.
person Marko Topolnik    schedule 11.05.2012
comment
Аргумент определенно не нулевой, когда я его передаю, и нулевой, когда он поступает в базовый конструктор. Кроме того, ни один из трех рассматриваемых классов не имеет в коде другого конструктора. - person dzirique; 11.05.2012
comment
Каким образом вы это установили? Предпочтительно, если вы можете показать код, который печатает эти результаты. Определите static T spy(T x) { System.out.println("x = " + x); return x; } и вызовите его в вызовах super, а также в конструкторе базового класса. - person Marko Topolnik; 11.05.2012
comment
Записав значение parent в консоль режима разработки GWT. - person dzirique; 11.05.2012
comment
Ваш метод ведения журнала, похоже, не работает, потому что на T нельзя ссылаться в нестатическом контексте в абстрактном классе. - person dzirique; 11.05.2012
comment
Подождите - вы не запускаете это как Java, а компилируете в Javascript, а затем запускаете это? Это изменило бы все. - person Marko Topolnik; 11.05.2012
comment
Что касается моего шпиона, попробуйте добавить ‹T›: static <T> T spy(T x) { System.out.println("x = " + x); return x; } или просто используйте Object и downcast, где это необходимо. - person Marko Topolnik; 11.05.2012
comment
Да, это приложение GWT, а не простая Java. Извиняюсь. - person dzirique; 11.05.2012
comment
Тогда я отказываюсь от своего категорического заявления, что этого не может быть. Я понятия не имею, какие ошибки могут возникнуть внутри GWT. - person Marko Topolnik; 11.05.2012