首先用我自己的理解,来描述一下我对java中的接口(狭义上的)和抽象类的理解。
先来看接口,形如:
public interface IncrementTool { public int increment(int a); }
在接口中,我们定义方法的名称、参数列表和返回类型,但是没有方法的实现。
然后我们可以写一些类去实现这个接口:
public class Increment1 implements IncrementTool{ @Override public int increment(int a) { return (a+1); } }
<pre name="code" class="java">public class Increment2 implements IncrementTool{ @Override public int increment(int a) { return (a+2); } }
在实现类里,把接口的方法具体实现了。
所以可以这么理解,接口定义了给出了一个方法的集合,告诉所有要实现它的类,可以做什么,但是具体怎么做,就要靠具体的类来实现。
在这个例子中就体现为,现在有很多人需要对一个int数进行增加的工作,但是每个人对increment的要求不一样,我每次要加1,他每次要加2。如果不用接口,让每个人自己写,可能会写出乱七八糟的函数名、参数列表等,对以后要再增加新的要求也不利。使用统一的一个方法集,就很容易实现今后的拓展,不同子类对接口不同的实现,也正是”多态“这一面向对象的概念在java中的体现。
对接口的使用需要注意的地方不多,只需要实现所实现接口中所有的方法即可,一个类可以实现多个接口。
下面来说说java的抽象类,形如:
public abstract class Base { private String s = "base class"; abstract public int increment(int a); public void print(int a){ System.out.println(s); } }
然后来写几个类去继承这个抽象类:
public class BaseInh1 extends Base{ public int increment(int a) { return (a+1); } @Override public void print(int a){ System.out.println("over writed"); } public static void main(String[] args) { Base b = new BaseInh1(); b.print(1); } }
输出的会是:over writed。这个子类继承了父类Base,父类中有一个抽象方法,那么子类中必须实现它,还重载了一个在父类中实现了的方法,而且在调用子类的这个方法的时候,执行的是子类的实现。
下面的继承是错的:
public class BaseInh1 extends Base{ @Override public void print(int a){ System.out.println("over writed"); } public static void main(String[] args) { Base b = new BaseInh1(); b.print(1); } }
因为这个子类没有实现父类的抽象方法。
但是下面这样子,是可以的:
public abstract class BaseInh1 extends Base{ }
也就是说,如果用非抽象类去继承一个抽象类,那么必须要实现抽象类的抽象方法,不抽象的方法是否重载是没有要求的,而抽象类又是可以被抽象类继承的,在子抽象类中,是可以什么都不做的(并不需要实现抽象方法)。
再来说说抽象类的一些特点或者要求(也许会漏掉):
1.抽象类中的成员,可以是抽象的(abstract),也可以是非抽象的,抽象的(abstract)成员可以有,但不是必须有的。
2.抽象类不可以实例化,也就是,不可以new一个抽象类的对象。
3.抽象类不可以用final关键字修饰,随便一想,如果是一个不可以继承的抽象类,就没有存在的意义了,抽象类的出现就是为了被继承的。
4.如果一个非抽象的类继承了抽象类,那么必须覆盖父类中的所有抽象成员。
说到这里,抽象类和接口的一些用法和特征算是说的差不多了,但是它们真正的妙用,连冰山一角都还没有看到,在很多设计模式中,会体现出接口和抽象类强大的作用。