2015-07-05 2 views
0

У меня есть суперкласс, называемый Параметр. Существует много разных типов параметров, и они, конечно, имеют разные методы. Проблема в том, что я инициализирую параметр как один из подстановок, но все же он не позволяет мне использовать события подкласса!Как использовать методы подкласса в суперклассе?

package com.lbg.c2; 

public class Parameter { 

private String type; 

public static final Parameter NumberParam = new NumberParam(); 
public static final Parameter StringParam = new StringParam(); 
public static final Parameter AnyTypeParam = new AnyTypeParam(); 
public static final Parameter AnimationParam = new AnimationParam(); 
public static final Parameter AudioParam = new AudioParam(); 
public static final Parameter CmpParam = new CmpParam(); 
public static final Parameter ComboOptionParam = new ComboOptionParam(); 
public static final Parameter ComboParam = new ComboParam(); 
public static final Parameter KeybParam = new KeybParam(); 
public static final Parameter LayerParam = new LayerParam(); 
public static final Parameter LayoutParam = new LayoutParam(); 
public static final Parameter ObjectParam = new ObjectParam(); 

public Parameter() { 

} 

public Parameter (String t) { 
    type = t; 
} 

public String getType() { 
    return type; 
} 

public static Parameter init (String t) { 
    if (t.equals("number")) { 
     return NumberParam; 
    } 
    else if (t.equals("string")) { 
     return StringParam; 
    } 
    else if (t.equals("any type")) { 
     return AnyTypeParam; 
    } 
    else if (t.equals("animation")) { 
     return AnimationParam; 
    } 
    else if (t.equals("audio")) { 
     return AudioParam; 
    } 
    else if (t.equals("comparision")) { 
     return CmpParam; 
    } 
    else if (t.equals("combo option")) { 
     return ComboOptionParam; 
    } 
    else if (t.equals("combo")) { 
     return ComboParam; 
    } 
    else if (t.equals("keyboard")) { 
     return KeybParam; 
    } 
    else if (t.equals("layer")) { 
     return LayerParam; 
    } 
    else if (t.equals("layout")) { 
     return LayoutParam; 
    } 
    else if (t.equals("object")) { 
     return ObjectParam; 
    } 
    else { 
     return new Parameter(); 
    } 
} 

}

Этот метод нашел статически в классе параметров так, когда вам это может инициализировать его из переданной строки.

 add.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      String types [] = {"number","string","any type","comparision","combo option", 
      "combo","object","layer","layout","keyboard","animation","audio"}; 
      JComboBox<String> box = new JComboBox<String>(types); 
      JLabel text = new JLabel ("Select the parameter type:\n"); 
      JPanel panel = new JPanel(); 
      panel.setLayout(new BorderLayout()); 
      panel.add(text, BorderLayout.NORTH); 
      panel.add(box, BorderLayout.SOUTH); 

      JOptionPane.showMessageDialog(frame, panel, "New Parameter", JOptionPane.QUESTION_MESSAGE); 

      Parameter p = Parameter.init((String) box.getSelectedItem()); 

      if (p instanceof NumberParam || p instanceof StringParam || p instanceof AnyTypeParam) { 
       String label = JOptionPane.showInputDialog(frame,"Parameter Label?","New Parameter",JOptionPane.QUESTION_MESSAGE); 
       p.setLabel(label); // it says it needs casting!! 
      } 
     } 

    }); 

Здесь теперь статический метод Parameter должен возвращать подкласс класса Parameter, но все же это не позволяет мне. Но теперь это подкласс, почему он не позволяет мне использовать его методы?

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

+1

уменьшить код основных частей, чтобы показать вашу проблему, я думаю, что пару строк будет достаточно –

+0

@LuigiCortese: Это уменьшенный много. – Makoto

+0

Что вы возвращаете в метод init(). Являются константами? Потому что, если нет, возможно, вы получите ошибки компиляции. Если вы пытаетесь создать экземпляр, вы должны использовать новый. –

ответ

2

A Parent класс никогда не знает, кто такие Child классы, которые унаследованы от него. Если вы определили метод в классе Child, к нему может быть доступен только вызов/вызвал экземпляр класса Child. Хотя обратное не верно, если метод определен в Parent Class, все экземпляры Child class могут получить к нему доступ/вызвать его.

Например: -

Object o = new String("Hi"); //will work because Object is parent class of String 
o.trim(); // can't call/will give compilation error because parent Object does not know child String's trim() 
if(o.getClass().equals(String.class)){ // check actual runtime class of o 
      String ss = (String) o; //typecasting 
      System.out.println(ss.trim()); // will work on String object 
     } 
+0

Спасибо! Это означает, что я должен изменить весь код сейчас –

+0

No @NajiKadri. Typecasting выполнит эту работу. используйте метод 'getClass()' на 'Parameter p', чтобы получить класс выполнения из' '' '' '' '' '' отбрасывает его в фактический subClass и вызывать требуемый метод на нем. –

+0

Можете ли вы показать мне пример, пожалуйста? Я не знал, как это сделать. Я попробовал, но это не сработало –

0

Вы не можете использовать методы подкласса, поскольку в

Parameter p = Parameter.init((String) box.getSelectedItem()); 

Вы объявляете p как тип Параметр. Вы сможете только вызвать методы, объявленные в параметре.

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

Parameter p = Parameter.init((String) box.getSelectedItem()); 
    NumberParameter np = (NumberParameter)p; 

Но я думаю, что вы думаете о Java наследования неправильно. Точка фабричного шаблона - это предоставление различных конкретных реализаций интерфейса, например Parameter. Это полезно в той мере, в какой метод setLabel() для разных подклассов делает что-то другое.

+0

Я знаю, но все же я назначаю его подклассу! Так что это должно быть конвертировать или что-то –

+0

Да, вы можете сделать ручное преобразование, которое называется «литье». – BladeCoder

0

Вы только когда-либо объявляя результат как Parameter и родительский класс не имеет знание того, что объявили его дети (или, что нарушило бы инкапсуляцию).

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

Образец подписи будет выглядеть следующим образом:

public static <T extends Parameter> T init(Class<T> clazz) throws InstantiationException, IllegalAccessException { 
    return clazz.newInstance(); 
} 

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

Образец вызов будет выглядеть примерно так:

// I want a NumberParameter 
NumberParameter p = Parameter.init(NumberParameter.class); 
Смежные вопросы