Расширение класса в java, но оно не будет наследовать свойства от суперкласса

#java #swt #extend #superclass

#java #swt #расширить #суперкласс

Вопрос:

хорошо, итак, в моей программе у меня есть несколько меток (которые находятся в массиве и прочее), в любом случае я хочу добавить свое собственное свойство во встроенный Label класс, так или иначе, поэтому я попытался его расширить

 public class LabelMod extends Label
  

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

 public void createContents()
{

    shlTictactoe = new Shell();
    shlTictactoe.setSize(450, 300);
    shlTictactoe.setText("TicTacToe");
  

затем существует 9 экземпляров следующего (g1x1, g1x2, g1x3, g2x1 и т.д.)

 LabelMod g1x1 = new LabelMod(shlTictactoe, SWT.NONE);
    g1x1.addMouseListener(new MouseAdapter()
    {
        @Override
        public void mouseDown(MouseEvent e)
        {
            changeSt(0);
        }
    });
    g1x1.setImage(SWTResourceManager.getImage(MainForm.class,
            "/res/blank.png"));
    g1x1.setBounds(10, 10, 64, 64);
  

а затем это, чтобы поместить их в массив

 createArray(g1x1, g1x2, g1x3, g2x1, g2x2, g2x3, g3x1, g3x2, g3x3);
  

я использую SWT для создания графического интерфейса и имею несколько меток в основной форме. Почему я не могу создать новый тип метки (с добавленными дополнительными свойствами)?

для этого конкретного примера в нем говорится: «Конструктор LabelMod(Shell, int) не определен»

зачем делать так, чтобы он просто наследовал материал из суперкласса? я попытался добавить конструктор в класс labelMod, но он также выдает неопределенную ошибку. Однако ошибка исправляется в основном классе.

 public LabelMod(Shell shlTictactoe, int none)   
    {
        super(shlTictactoe,none);
        // TODO Auto-generated constructor stub
    }
  

Другая идея, которая у меня была, заключалась в том, чтобы просто присвоить некоторые метки LabelMods, но поскольку они не одного типа, он жалуется.
ее пример того, что я имею в виду:

 Label g1x1 = new Label(shlTictactoe, SWT.NONE);     
g1x1.setImage(SWTResourceManager.getImage(MainForm.class,
            "/res/blank.png"));
g1x1.setBounds(10, 10, 64, 64);
  

а затем позже у меня есть массив

 public LabelMod[] labelArray = new LabelMod[9];
  

и затем я присваиваю это метке

 labelArray[0] = g1x1;
  

очевидно, потому что это разные типы, это не работает, но, возможно, его можно преобразовать или что-то в этом роде?

примечание: все работает, если я просто использую обычную Label версию вместо моей модифицированной версии, поэтому я знаю, что проблема не в этом.

EDIT:

here is the class In full if it helps

 public class LabelMod extends Label {


public LabelMod() throws HeadlessException
{
    super();
    // TODO Auto-generated constructor stub
}

public LabelMod(String text, int alignment) throws HeadlessException
{
    super(text, alignment);
    // TODO Auto-generated constructor stub
}

public LabelMod(String text) throws HeadlessException
{
    super(text);
    // TODO Auto-generated constructor stub
}

public LabelMod(Shell shlTictactoe, int none)   
{
    super(shlTictactoe,none);
    // TODO Auto-generated constructor stub
}

public boolean isActivated;

public boolean isActivated()
{
    return isActivated;
}

public void setActivated(boolean isActivated)
{
    this.isActivated = isActivated;
}

}
  

также я обнаружил, что при наведении курсора мыши на исходный (рабочий) Label(shlTictactoe, SWT.NONE); формат

 Label(Composite parent, int style)
  

РЕДАКТИРОВАТЬ 2:
в addMouseListener нем также есть ошибки

Метод addMouseListener(MouseListener) в компоненте типа неприменим для аргументов (new MouseAdapter(){})

и для setImage меня снова становится неопределенным

Метод setImage(Image) не определен для типа labelMod

РЕДАКТИРОВАТЬ 3 Одна деталь, которую я не считал важной, но может быть жизненно важной для проблемы … это мой импорт для LabelMod класса — имейте в виду его проект SWT

 import java.awt.HeadlessException;
import java.awt.Label;

import org.eclipse.swt.widgets.Shell;
  

РЕДАКТИРОВАТЬ 4

хорошо, поэтому я добавил соответствующий импорт (на этот раз swt — убедился), так что теперь мой импорт:

 import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
  

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

 org.eclipse.swt.SWTException: Subclassing not allowed
at org.eclipse.swt.SWT.error(SWT.java:4282)
at org.eclipse.swt.SWT.error(SWT.java:4197)
at org.eclipse.swt.SWT.error(SWT.java:4168)
at org.eclipse.swt.widgets.Widget.error(Widget.java:468)
at org.eclipse.swt.widgets.Widget.checkSubclass(Widget.java:313)
at org.eclipse.swt.widgets.Widget.<init>(Widget.java:148)
at org.eclipse.swt.widgets.Control.<init>(Control.java:110)
at org.eclipse.swt.widgets.Label.<init>(Label.java:101)
at Main.LabelMod.<init>(LabelMod.java:16)
at Main.MainForm.createContents(MainForm.java:99)
at Main.MainForm.open(MainForm.java:39)
at Main.MainForm.main(MainForm.java:26)
  

и в журнале ошибок я вижу это:

 Designer [1.1.0.r37x201109091012.201110120013]: new Label(shell, SWT.NONE)
  

http://pastebin.com/ru1QCU0A для остальных

Комментарии:

1. «Я получаю стек ошибок» не очень полезно. Что было бы полезно, так это короткая, но полная программа вместе с подробным описанием ошибок. Пожалуйста, прочитайте tinyurl.com/so-hints

2. да, спасибо, я на самом деле этого не знал, буду иметь в виду

3. Переопределить checkSubclass с помощью пустого метода. Или, еще лучше, не делайте этого. Смотрите ниже.

Ответ №1:

Здесь у вас есть пара проблем.

Во-первых, вы смешиваете org.eclipse.swt.widgets.Label и java.awt.Label . Вы (я думаю) пытаетесь переопределить org.eclipse.swt.widgets.Label , это означает, что для этого вам нужен подходящий конструктор. Это означает:

 public LabelMod(Shell parent, int style)
{
    super(parent, style);
}
  

Вам не нужен ни один из конструкторов, которые принимают String аргумент. Это подходит для java.awt.Label , а не для SWT.

Во-вторых, вы уверены, что хотите переопределить Label ? Рекомендуемый рабочий процесс SWT заключается в создании a Composite , который обертывает или содержит a Label , и для выполнения вашей пользовательской работы в классе обертывания. На самом деле существуют встроенные проверки, которые вам нужно переопределить, чтобы даже иметь возможность подкласса SWT widget. Вам придется переопределить следующий метод:

 protected void checkSubclass()
{
    /* Allow us to subclass this widget. */
}
  

В-третьих, я не уверен, что это за createContents метод Label . Поскольку SWT является оболочкой для собственной оконной системы, разные Label s могут иметь разные частные реализации на разных платформах. Например, в Mac OS нет createContents метода on Label или любого из его предков, что указывает на то, что это частный метод, который вы не можете переопределить. Вам нужно будет найти другой метод переопределения, чтобы изменить поведение, которое вы видите.

С этой целью я спрошу еще раз — вы уверены, что вам действительно нужно переопределить Label , а не просто создать оболочку вокруг него, используя свой собственный Composite ? Я пишу приложения SWT в течение нескольких лет, и у меня возникла необходимость расширить виджет SWT ровно один раз, и только для тривиального изменения, в то время как я создал бесчисленное Composite количество файлов, которые содержат или переносят другие виджеты.

Комментарии:

1. хорошо, спасибо за это, на самом деле не думал об этом подходе — главным образом потому, что я не совсем понимал, что такое composite или что-то в этом роде. Я просто подумал, что могу относиться к нему как к любому другому классу. Это довольно хорошо объяснило это bit.ly/nWl1yN

Ответ №2:

Конструкторы не наследуются, поэтому вам нужно определить свой собственный конструктор для вашего подкласса. Я думаю, что если вы попробуете еще раз внимательно, вы обнаружите, что показанный вами код работает (при условии, что вы добавите недостающую точку с запятой в конце super строки.

Затем, что касается вашего массива, вы можете назначить экземпляр подкласса переменной суперкласса, но не наоборот. Это говорит о том, что массив типа Label[] будет работать просто отлично; он может содержать как обычные Label s, так и labelMod экземпляры.

Я должен отметить, что Java имеет набор очень строгих соглашений об именовании; классы всегда называются начальными заглавными буквами. Если вы нарушите это правило, опытному глазу будет намного труднее прочесть ваш код.

Ответ №3:

Редактировать:

java.awt.Label имеет 3 типа конструкторов

 Label()
Label(String)
Label(String, int)
  

и org.eclipse.swt.widgets.Label имеет 1 тип конструктора

 Label(Composite, int)
  

Как вы смогли вызвать это одновременно

 public labelMod(Shell shlTictactoe, int none)   
    {
        super(shlTictactoe,none);
        // TODO Auto-generated constructor stub
    }

public LabelMod(String text, int alignment) throws HeadlessException
{
    super(text, alignment);
    // TODO Auto-generated constructor stub
}
  

Я думаю, вы смешиваете SWT и AWT. Может ли это быть правдой?

Комментарии:

1. итак, если я не могу вызвать это из super, то что мне нужно сделать, чтобы исправить проблему? Если я нажимаю на предложение «создать конструктор», оно создает это public labelMod(Shell shlTictactoe, int none) (я добавил в супер бит, который ниже)

2. i в какой упаковке/ банке помещен класс «Label»? Говорим ли мы о java.awt.Label? Я думаю, мы говорим о «org.eclipse.swt.widgets. Этикетка»

3. Да, класс Label находится в org.eclipse.swt.widgets.Label

4. но prject — это проект swt, а основной класс — окно приложения swt. как бы я смешивал awt, если бы я никогда не делал ничего, связанного с awt? имейте в виду, что все работает, если я использую обычные метки, проблема возникает только тогда, когда я пытаюсь использовать свою модифицированную версию с дополнительным свойством LabelMod

5.оооооо… да, мой импорт — import java.awt.HeadlessException; import java.awt.Label; import org.eclipse.swt.widgets.Shell; я просто использовал функцию organize imports, поэтому eclipse, должно быть, добавил неправильные. вы знаете, что мне нужно добавить, чтобы изменить это на swt?

Ответ №4:

Я свингер, поэтому я не использовал swt, но похоже, что вы не должны переопределять класс Label, и есть проверки, которые вас останавливают.

Также проверьте свои конструкторы, вы можете передавать в super только переменные, которые может принимать конструктор суперкласса. Поэтому проверьте javadock. Вы не можете привести суперкласс к его подклассу, если он не был создан как этот подкласс.

Ответ №5:

Я думаю, что, возможно, произошло то, что при первоначальном создании LabelMod у вас был неправильный импорт, возможно, java.awt.Label, а не swt. Используемый вами инструмент, Eclipse, я полагаю, создал для вас все конструкторы на основе выбранного суперкласса (т.Е. ярлык, но не org.eclipse.swt.widgets.Метка).

Итак, чтобы ответить на вопрос, у вас не должно возникнуть проблем с расширением org.eclipse.swt.widgets.Помечайте и добавляйте свои собственные свойства и методы или переопределяйте существующие методы, но, особенно если вы используете инструменты, которые создают для вас много «заглушки» кода, вам нужно сначала убедиться, что у вас есть правильный суперкласс. Возможно, это то, что вы ищете:

 import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;

public class LabelMod extends Label {

public LabelMod(Composite parent, int style) {
    super(parent, style);
    // TODO Auto-generated constructor stub
}

public boolean isActivated;

public boolean isActivated() {
    return isActivated;
}

public void setActivated(boolean isActivated) {
    this.isActivated = isActivated;
}

}
  

Ответ №6:

Нет конструктора, который соответствует сигнатуре вашего конструктора (посмотрите здесь), поэтому, когда вы вызываете

super(shlTictactoe,none)

он не может найти соответствующий конструктор на label. Вам нужно передать String и int .

Комментарии:

1. у меня действительно есть это, я просто не включил его, потому что это, похоже, не является частью проблемы. Ошибка в моем основном классе фактически исчезла, когда я добавил этот конструктор, но вместо этого я получил ошибки в новом конструкторе. Я попробую добавить больше к исходному вопросу

2. затем удалите этот конструктор. Кроме того, удалите весь код из вашего подкласса, кроме конструкторов и добавленного вами свойства. Создание подкласса, который работает на базовом уровне, должно быть тривиальным.

Ответ №7:

Подкласс наследует, однако методы доступа суперкласса по своей сути недоступны. Простой способ получить / установить значения из суперкласса — это настроить методы делегирования в вашем подклассе.

Например, если суперкласс имеет атрибут «label», в вашем подклассе вы должны создать метод:

 public String getLabel(){
    return super.getLabel();
}

public void setLabel(String label){
    super.setLabel(label);
}
  

В большинстве IDE есть способы легко генерировать методы делегирования без ручного кодирования их всех. Например, в Netbeans «alt insert» вызовет меню параметров генерации кода, в котором вы можете выбрать делегатов, а затем выбрать, для какого включенного класса или суперкласса создавать методы делегирования.

Комментарии:

1. Конечно, все, что вы говорите о делегировании методов, верно, за исключением того, что это не имеет ничего общего с какой-либо проблемой, которую он видит; все средства доступа в Label классе являются общедоступными. Его проблема только в том, что конструкторы не наследуются.

2. Правда, я стрелял с бедра без какой-либо трассировки стека. Мое первоначальное прочтение проблем выглядело так, как будто у него были проблемы с доступом к атрибутам в суперклассе, т.Е. Строка «почему dosent просто наследует материал из суперкласса?» Но я пропустил ошибку конструктора в тексте над ней. Несмотря на это, это наследование в конструкторе.