我想问一个大家都知道,但我今天却很疑惑的一个问题(我以前从没注意过)。我想定义一个类(这个类 继承  接口抽象类),如果想通过这个类实例一个对象的话,我们必须实现所继承接口或抽象类中的全部方法。但是,大家都知道:如果想实现事件监听,可以继承接口或抽象类(适配器类)。如果借助接口的话,需要实现接口中全部方法;如果借助适配器类(如MouseAdapter),只需实现你想调用的方法。所以,现在我就迷糊了……
同样是抽象类,对于适配器类(如MouseAdapter)怎么就不用实现其全部方法呢?
附:
public abstract class MouseAdapter
extends Object
implements MouseListener, MouseWheelListener, MouseMotionListener

解决方案 »

  1.   

    抽象类是可以继承的,但是不能用非接口继承接口
    抽象类中的方法并非都是抽象方法,但是接口中都是抽象方法
    当你继承一个类的时候(继承,非实现),你可以去override父类的非抽象方法,也可以不去override。
    但是如果是父类的抽象方法,那么你在子类中是必须要去实现
    abstract class A{
    abstract void run();
    void fly(){ }
    }
    class B extends A{ void run() {
    }


    }
      

  2.   

    MouseAdapter 源码public abstract class MouseAdapter implements MouseListener, MouseWheelListener, MouseMotionListener {
        /**
         * {@inheritDoc}
         */
        public void mouseClicked(MouseEvent e) {}    /**
         * {@inheritDoc}
         */
        public void mousePressed(MouseEvent e) {}    /**
         * {@inheritDoc}
         */
        public void mouseReleased(MouseEvent e) {}    /**
         * {@inheritDoc}
         */
        public void mouseEntered(MouseEvent e) {}    /**
         * {@inheritDoc}
         */
        public void mouseExited(MouseEvent e) {}    /**
         * {@inheritDoc}
         * @since 1.6
         */
        public void mouseWheelMoved(MouseWheelEvent e){}    /**
         * {@inheritDoc}
         * @since 1.6
         */
        public void mouseDragged(MouseEvent e){}    /**
         * {@inheritDoc}
         * @since 1.6
         */
        public void mouseMoved(MouseEvent e){}
    }它的确是抽象类,但是没有抽象方法,全部都是具体的方法所以你可以想实现什么方法就实现什么但是如果一个抽象类中有抽象方法,那无论几个你都得通通实现了接口也是同样道理
      

  3.   

    你的理解有这样几条不正确甚至是完全错误的:
    第一,一个普通类如果继承自抽象类,不是必须实现抽象类的所有方法,抽象类在定义方法的时候是可以实现的,普通类必须实现的是抽象类里面只定义没有实现的,对于实现的方法可以不用再次实现(那就覆盖了)
    第二,适配器类是抽象类这个没问题,但是适配器里面所有的方法都是实现的,给你一个例子/*
     * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
     * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     */package java.awt.event;/**
     * An abstract adapter class for receiving window events.
     * The methods in this class are empty. This class exists as
     * convenience for creating listener objects.
     * <P>
     * Extend this class to create a <code>WindowEvent</code> listener
     * and override the methods for the events of interest. (If you implement the
     * <code>WindowListener</code> interface, you have to define all of
     * the methods in it. This abstract class defines null methods for them
     * all, so you can only have to define methods for events you care about.)
     * <P>
     * Create a listener object using the extended class and then register it with
     * a Window using the window's <code>addWindowListener</code>
     * method. When the window's status changes by virtue of being opened,
     * closed, activated or deactivated, iconified or deiconified,
     * the relevant method in the listener
     * object is invoked, and the <code>WindowEvent</code> is passed to it.
     *
     * @see WindowEvent
     * @see WindowListener
     * @see <a href="http://java.sun.com/docs/books/tutorial/post1.0/ui/windowlistener.html">Tutorial: Writing a Window Listener</a>
     *
     * @author Carl Quinn
     * @author Amy Fowler
     * @author David Mendenhall
     * @since 1.1
     */
    public abstract class WindowAdapter
        implements WindowListener, WindowStateListener, WindowFocusListener
    {
        /**
         * Invoked when a window has been opened.
         */
        public void windowOpened(WindowEvent e) {}    /**
         * Invoked when a window is in the process of being closed.
         * The close operation can be overridden at this point.
         */
        public void windowClosing(WindowEvent e) {}    /**
         * Invoked when a window has been closed.
         */
        public void windowClosed(WindowEvent e) {}    /**
         * Invoked when a window is iconified.
         */
        public void windowIconified(WindowEvent e) {}    /**
         * Invoked when a window is de-iconified.
         */
        public void windowDeiconified(WindowEvent e) {}    /**
         * Invoked when a window is activated.
         */
        public void windowActivated(WindowEvent e) {}    /**
         * Invoked when a window is de-activated.
         */
        public void windowDeactivated(WindowEvent e) {}    /**
         * Invoked when a window state is changed.
         * @since 1.4
         */
        public void windowStateChanged(WindowEvent e) {}    /**
         * Invoked when the Window is set to be the focused Window, which means
         * that the Window, or one of its subcomponents, will receive keyboard
         * events.
         *
         * @since 1.4
         */
        public void windowGainedFocus(WindowEvent e) {}    /**
         * Invoked when the Window is no longer the focused Window, which means
         * that keyboard events will no longer be delivered to the Window or any of
         * its subcomponents.
         *
         * @since 1.4
         */
        public void windowLostFocus(WindowEvent e) {}
    }
    这里面的public void windowLostFocus(WindowEvent e) {} 实际上是已经实现了,只是方法体当中没有做任何事情,所以你继承这个适配器的时候,没有任何必须要你实现的方法,你可以选择实现的方法实际上都是重写覆盖了父类的对应方法的空实现
      

  4.   

    1、抽象类和适配器,适配器实现了抽象类的全部方法,只不过实现方式都是空的,如7楼所示的代码,你在使用适配器的时候只需要对你感兴趣的方法进行覆盖就可以了,而如果使用抽象类,则需要实现全部的方法。
    2、抽象类和接口的选择,参考下面的文章吧,这是我在网上看到记录下来的,分析的挺好的:http://www.cnblogs.com/luochengor/archive/2011/08/11/2134828.html
      

  5.   

    嗯,你提的第一条,我说的不对,我现在明白了。
    但是,public void windowLostFocus(WindowEvent e) {} 这样怎么就叫实现了呢?
      

  6.   


    public void windowLostFocus(WindowEvent e);
    这样一行就是光声明有这样一个方法,是没有方法体实现的加了 {} 尽管中间没有内容,但它的确是一种实现,什么都不做的实现
      

  7.   

    另外提一点学习Java,你至少有两个权威的东西必须看1 JDK Doc
    2 Java src,它位于你JDK目录下的src.zip中有人说可以看JDK提供的demo,我没看过,不评价
      

  8.   

    刚刚说的不明确,其实就是看是不是抽象方法 public void windowLostFocus(WindowEvent e) {} 上面没有用abstract关键字,这个就是普通的方法
    如果是
    public abstract void windowLostFocus(WindowEvent e){}这样声明的抽象方法在继承的时候就一定要实现
      

  9.   

    SWING的所有适配器为了方便使用,都是没有abstract声明的抽象方法的但是其他的适配器可未必
      

  10.   

    空实现也是实现的一种,这样不就省了程序员的工作了吗?
    但是空实现本身是没有意义的,所以才把Adapter类定义成抽象类,以驱使程序员用具体的适配器来代替这种“什么都不做”的适配器。
    总的来说,还是为了方便编程,或者说为了照顾到各种口味的程序员的需要。
      

  11.   

    是不是没有定义abstract方法的类也可以声明为抽象类?
      

  12.   


    抽象类必须有abstract关键字修饰抽象方法必须加 abstract关键字修饰(我之前说的 public void XXX(XXX); 是错的。。  无视它)这样写  public abstract returnType MethodName(ParaList);
    就是抽象方法的声明了
      

  13.   

    一开始看不太懂
    java的抽象类和C++的抽象类很不同呀……
      

  14.   

    明白的
    我纠结的是某些适配器类,被声明为成抽象类,但却没有抽象方法
    C++中是不允许这样的,以前以为类这部分java和C++差不太多呢,真是汗呀……
      

  15.   


        Java里面的抽象类可以没有抽象方法,这种情况我认为是可能出于这种考虑,如果以上适配器的类实现了适配器的接口,并空实现了所有接口的方法,如果不定义为抽象的,你就可以直接实例化这个类将其当成你的适配器用,但是这样一来其实你的适配器是没有任何意义的,所以将其定义为抽象。
        那么为什么既然适配器需要你实现方法,为什么不将你必须实现的方法定义为抽象的呢,那是因为它压根就不知道你 必须实现哪一个,因为接口中定义的方法你只要选择实现一部分就可以了(而这一部分又是不确定但必须的)。所以搞了一个全部空实现的抽象类来帮你实现接口。这样你既不能直接实例化这个抽象了,又不必非要实现接口的所有方法。
        不过我觉得这样设计也有问题,就是你的自定义适配器继承该抽象类,又不实现任何方法也是没有问题的,这样你可以实例化你的没有任何实例化接口的方法的类,和直接实例化它的抽象类没有区别,其实就违背了它将那个类搞成抽象类的初衷了。不过它已经是最好的方式了,非要让程序,让设计去约束程序员的行为是不现实的也是愚蠢的,毕竟人是好说话的,可以交流的,听得懂话得,有思想的嘛,不像计算机那么愚蠢。
      

  16.   

    如果他内部抽象方法没有实现完,编译一定会报错。无论Eclipse和JAVAC都会报错。抽象方法是提醒你一定要完善一下我这个方法,一定不能忘了;至于非抽象方法,你完不完善都没所谓
      

  17.   

    同意29楼的说法。此外,抽象类要写抽象方法、非抽象方法,多多少少都灌输了创作者的个人意志。他认为funcA()方法很重要,并且子类必然会用到,就会定义为抽象的,以便后人使用时都能复写。