是否可以创建一个附加了泛型的对象,它是抽象类的扩展?

时间:2016-02-03 01:09:33

标签: java swing generics abstract

我正在制作一个抽象类(我们称之为Screen),它是JPanel的扩展。我希望将来用户/我自己能够从中扩展。那部分不是问题。

我也试图创建一个类(让我们称之为“ScratchDrawingProject”),它是JFrame的扩展,并且它附加了一个泛型。这个类还有一个上面提到的抽象类的实例作为要添加到它的屏幕。

我希望用户在项目的main方法(在他们创建的其他随机文件中)能够创建ScratchDrawingProject的实例,其中泛型是Screen的扩展。在ScratchDrawingProject的构造函数中,我希望将Screen变量实例化为用户传入的Screen扩展的新对象。

到目前为止屏幕我有:

public abstract class Screen extends JPanel{

    private JFrame parent;
    private Graphics2D GRAPHICS;

    //CONSTRUCTOR
    public Screen(JFrame parent){
        this.parent = parent;
        parent.add(this);
        setBounds([bounds]);
        repaint();
    }

    //basically the stuff you would put in the extension's constructor, but this method
    //can be created by an IDE like Eclipse 
    public abstract void start();      

    //basically the paintComponent() for the extension, but in disguise for ease of
    //use of newcomers that aren't *too* knowledgeable of Java.
    public abstract void drawMethod(); 

    //repaint() in disguise
    public void draw(){
        repaint();
    }        

    public void paintComponent(Graphics g){
        GRAPHICS = (Graphics2D) g;
        draw();
    }

    //...methods that extensions of this class can put in their "drawMethod" definition
    //that call GRAPHICS.*, so that the user never even has to see the word Graphics
    //as they are creating their extension...

}

到目前为止ScratchDrawingProject我有:

public class ScratchDrawingProject<ScreenType> extends JFrame{

    private Screen screen;

    public ScratchDrawingProject(){
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds([bounds]);
        setVisible(true);
        screen = (ScreenType)new Object(); //which gives me a runtime error because I can't
        screen.setParent(this);            //cast Object to Screen, and I can't make
        screen.start();                    //screen a new ScreenType() because that
    }                                      //gives me a compiling error saying 
                                           //ScreenType can't be instantiated.
}

我也尝试过做一些我认为最有可能变得如此愚蠢的事情,它会给我一个编译错误,那就是:

public class ScratchDrawingProject<ScreenType extends Screen> extends JFrame{

永远不会猜到这不会让我产生编译错误纯粹是因为它在概念中看起来多么荒谬。相反,我在实例化屏幕时再次出现错误,无论我是否尝试过

screen = new ScreenType();

仍然告诉我ScreenType无法实例化,或

screen = (ScreenType)new Screen();

告诉我Screen无法实例化(我理解的是因为它是抽象的)

总之!我的目标是让人们能够创建自己的课程

public class Whatever{

    public static void main(String[] args){
        ScratchDrawingProject<IDKScreen> screen = new ScratchDrawingProject<IDKScreen>();
    }
}

public class IDKScreen extends Screen{

    start(){
        //do stuff!
    }

    drawMethod(){
        //do more stuff!
    }
}

并且Whatever自动创建一个ScratchDrawingProject,创建一个IDKScreen实例,添加它,调用IDKScreen.repaint()来实例化GRAPHICS以备将来使用,最后调用IDKScreen的start()并执行用户放入的任何内容。

1 个答案:

答案 0 :(得分:2)

所以,首先,你似乎对Swing绘画的工作方式缺乏了解。我建议您仔细查看Painting in AWT and SwingPerforming Custom Painting,因为您似乎违反了一些非常重要的概念。

从你开始抽象Screen ...

public abstract class Screen extends JPanel{

    // Bad idea
    //private Graphics2D GRAPHICS;

    //CONSTRUCTOR
    public Screen(){
        // Generally a bad idea, use getPreferredSize instead
        //setBounds([bounds]);
        // Pointless, you're not displayable yet
        //repaint();
    }

    //basically the stuff you would put in the extension's constructor, but this method
    //can be created by an IDE like Eclipse 
    public abstract void start();      

    //basically the paintComponent() for the extension, but in disguise for ease of
    //use of newcomers that aren't *too* knowledgeable of Java.
    //public abstract void drawMethod(); 
    // Which based on what you seem to be trying to do, you would be one

    //repaint() in disguise
    public void draw(){
        repaint();
    }        

    @Override
    protected void paintComponent(Graphics g){
        Graphics2D g2d = (Graphics2D) g.create();
        // Some painting stuff...
        performPaint(g2d);
        g2d.dispose();
        // This is probably among the worse things you can do, simply put
        // don't change or modify the state of a component from which in paint
        // method which might, directly or indirectly, trigger a repaint,
        // you're just asking for trouble
        //draw();
    }

    // Basically, this gets called when the component needs to be repainted
    protected abstract void performPaint(Graphics2D g2d);

    //...methods that extensions of this class can put in their "drawMethod" definition
    //that call GRAPHICS.*, so that the user never even has to see the word Graphics
    //as they are creating their extension...

}

接下来,您需要定义ScratchDrawingProject类的要求......

public class ScratchDrawingProject<S extends Screen> extends JFrame{

    private S screen;

    public ScratchDrawingProject(S screen){
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            this.screen = screen;
            add(screen);
            pack();
            setVisible(true);
            screen.start();                    
    }                                      

    public S getScreen() {
        return screen;
    }

}    

基本上这只是说S必须是扩展Screen的类的实例

现在,我们可以定义Screen ...

的实现
public class MyAwesomeScreen extends Screen {

    @Override
    public void start() {
        // Broom
    }

    @Override
    protected void performPaint(Graphics2D g2d) {
        // paint me a rainbow
    }
}

然后为我们的实现创建ScratchDrawingProject的实例......

MyAwesomeScreen myAwesomeScreen = new MyAwesomeScreen();
ScratchDrawingProject<MyAwesomeScreen> myScratchDrawingProject = new ScratchDrawingProject<>(myAwesomeScreen);

那么问题就变成了原因? myScratchDrawingProject似乎并不关心Screen的实施,只是它是Screen的一个实例,但这只是一个不合适的例子。 - 上下文观察