简体   繁体   中英

Extending a class in java but it wont inherit properties from the superclass

ok so on my program i have some labels (which are in an array and stuff) anyway i want to add my own property to the inbuilt Label class, anyway so i tried extending it

public class LabelMod extends Label

but whenever i try to change it so it creates my new type of label instead of the default in the createContents() method it doesn't seem to inherit the original label properties and i get a stack of errors

public void createContents()
{

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

there is then 9 instances of the following (g1x1, g1x2, g1x3, g2x1 etc)

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);

and then this to place them in an array

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

i am using SWT to create a gui and a have a few labels on the main form. Why cant I create the new type of label (with the extra properties i added)?

for this particular example it says "The constructor LabelMod(Shell, int) is undefined"

why dosent it just inherit the stuff from the superclass? i tried adding the constuctor to the labelMod class but it also gives an undefined error. The error gets fixed in the main class however.

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

Another idea I had was to just assign some of the Labels to LabelMods but because they arent the same type it complains. hers an example of what i mean:

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

and then later on I have an array

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

and then I assign this to the label

labelArray[0] = g1x1;

obviously because they are different types it dosent work but perhaps its possible to convert it or something?

note: everything works if I just use the normal Label instead of my modified version so i know thats not the problem.

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;
}

}

also i found if i hover over the original (working) Label(shlTictactoe, SWT.NONE); the format is

Label(Composite parent, int style)

EDIT 2: there are also errors with addMouseListener it says

The method addMouseListener(MouseListener) in the type Component is not applicable for the arguments (new MouseAdapter(){})

and for setImage i get undefined again

The method setImage(Image) is undefined for the type labelMod

EDIT 3 One detail i didnt think to be important but could be vital to the issue... these are my imports for the LabelMod class - keep in mind its an SWT project

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

import org.eclipse.swt.widgets.Shell;

EDIT 4

okay so i added in the appropriate import (swt this time - made sure) so now my imports are:

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

but now i get a runtime error, and if i go into the designer view all the labels dont display properly here is what i get in the console:

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)

and in the error log i ge this:

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

http://pastebin.com/ru1QCU0A for the rest

You've got a couple of problems here.

First, you're mixing up org.eclipse.swt.widgets.Label and java.awt.Label . You're (I think) trying to override org.eclipse.swt.widgets.Label , this means that you need to have a suitable constructor for that. This means:

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

You do not need any of the constructors that take a String argument. This is suitable for java.awt.Label , not for SWT.

Second, are you sure you want to override Label ? The recommended SWT workflow is to build a Composite that wraps or contains a Label and to do your custom work in the wrapping class. There are actually built-in checks that you'll need to override to even be able to subclass an SWT widget. You'll have to override the following method:

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

Third, I'm not sure what the createContents method on Label is. Since SWT is a wrapper around the native window system, the different Label s may have different private implementations on different platforms. On Mac OS, for example, there is not createContents method on Label or any of its ancestors, which would indicate that this is a private method that you can't override. You'll need to find a different method to override to change the behavior you're seeing.

To that end, I'll ask again - are you sure that you really need to override Label and not simply create a wrapper around it using your own Composite ? I've been writing SWT applications for several years and I've had the need to extend an SWT widget exactly once , and only for a trivial change, whereas I've created countless Composite s that contain or wrap other widgets.

Constructors aren't inherited, so you do need to define your own constructor for your subclass. I think if you try again carefully you will find that the code you've shown works (given you add the missing semicolon at the end of the super line.

Then regarding your array, you can assign an instance of a subclass to a superclass variable, but not the other way around. This suggests that an array of type Label[] would work just fine; it could hold regular Label s as well as labelMod instances.

I should point out that Java has a set of very strong naming conventions; classes are always named with initial capital letters. If you violate this, it makes your code a lot harder to read for an experienced eye.

EDIT:

java.awt.Label has 3 types of constructor

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

and org.eclipse.swt.widgets.Label has 1 type of constructor

Label(Composite, int)

How you were able to call this at the same time

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
}

I think you are mixing SWT and AWT. Could this be true?

I'm an swing guys so I haven't used swt but it looks like you are not supposed to overide the Label class and there are checks to stop you.

Also check your constructors, you can only pass variables to super that the superclass constructor can take. So check the javadock. You can't cast a superclass to its subclass unless it was constructed as that subclass.

I think what may have happened is that when you originally created LabelMod, you had the wrong import, possibly java.awt.Label rather than swt. The tool you used, Eclipse I assume, created all the constructors for you based on the superclass chosen (ie Label but not org.eclipse.swt.widgets.Label).

So, to answer the question, you should have no problem extending org.eclipse.swt.widgets.Label and adding your own properties and methods or overriding existing methods but, especially if using tools that create a lot of "stub" code for you, you need to make sure you have the right superclass first. Maybe this is what you are looking for:

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;
}

}

The subclass does inherit, however the superclass accessor methods are not inherently accessible. An easy way to be able to get/set values from the superclass is to setup delegate methods in your subclass.

For example, if the super class has an attribute "label", in your sub class you would create a method:

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

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

Most IDEs have ways to generate delegate methods easily without hand coding them all. In Netbeans for example "alt+insert" will bring up a code generation options menu in which you can select delegates and then choose which included class or superclass to create delegate methods for.

There is no constructor that matches the signature of your constructor (look here ), so when you call

super(shlTictactoe,none)

it can't find the appropriate constructor on label. You need to pass in a String and an int.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM