写在前面:该文章出自一个Java初学者,文章内容多为其实验结果,欢迎斧正与赐教
抽象类
概念:如果某个类被abstract关键字修饰,则该类为抽象类,其中若存在方法且方法也被abstract修饰,且没有内容,则该方法为抽象方法。概念生涩难懂,附上代码:
public abstract class AbstractClass {
public abstract void getLoca(int row, int col);
}
其中,具有两个参数的getLoca方法即为抽象方法,AbstractClass类即为抽象类。抽象,何谓抽象,没有实体就是抽象。在该类中,getLoca方法只有名称,返回类型与参数,并无具体代码与大括号{},这就是抽象类的基本定义。
tips:若方法被abstract修饰,则该类必须为抽象类,且其子类全部为抽象类。getLoca方法默认为不可见(只是声明了是abstract类型而已),所以要使其具有实在意义,要将其用public或protected修饰。
实现方法:
(1)产生一个类继承自该抽象类并完善其中抽象方法
import ps.laod.abstract_core.core.AbstractClass;
public class Demo extends AbstractClass {
private int row;
private int col;
public Demo() {
}
@Override
public void getLoca(int row, int col) {
System.out.println("[" + row + "," + col + "]");
}
@Override
public String toString() { //覆盖toString方法是为了new出该类实例时,直接输出的结果
return "[" + row + "," + col + "]"; //不再为地址而是toString内容
}
}
此种方法只能在该类中将代码写死,局限性颇大。
(2)在需要调用该抽象方法时进行完善并实例化
public class Test {
public static void main(String[] args) {
final int colllllll = 45;
final int rowwwwww = 60;
AbstractClass abc = new AbstractClass() {
@Override
public void getLoca(int row, int col) {
System.out.println("row和col的和为" + (rowwwwww + colllllll));
}
};
abc.getLoca(20, 20);
}
}
row和col的和为105
上为输出。可见在实现的getLoca方法中使用了colllllll常量和rowwwwww常量,这是方法1所做不到的,但在加载速度上不知二者有何不同,我还需要了解一下classLoader的相关机制,下文再说。
总之目前由于方法二具有更好的适应性且编写起来更简便,我们大多使用方法二来实现抽象方法。
使用实例
现在定义三个类:门,铁门和防盗门,其中门为抽象类。三种门具有特点:
门:开,关,功能;
铁门:开,关,结实;
防盗门:开,关。警报;
package ps.laod.door;
public abstract class Door {
public abstract void open();
public abstract void close();
public abstract void function();
}
package ps.laod.alerm_door;
import ps.laod.door.Door;
public class AlermDoor extends Door{
@Override
public void open() {
System.out.println("门可以开");
}
@Override
public void close() {
System.out.println("门可以关");
}
@Override
public void function() {
System.out.println("可以警报!");
}
}
package ps.laod.iron_door;
import ps.laod.door.Door;
public class IronDoor extends Door{
@Override
public void open() {
System.out.println("铁门可以开!");
}
@Override
public void close() {
System.out.println("铁门可以关!");
}
@Override
public void function() {
System.out.println("铁门是结实的");
}
}
package ps.laod.door.demo;
import ps.laod.alerm_door.AlermDoor;
import ps.laod.iron_door.IronDoor;
public class Demo {
public static void main(String[] args) {
AlermDoor alermDoor = new AlermDoor();
IronDoor ironDoor = new IronDoor();
alermDoor.function();
ironDoor.function();
}
}
输出如下:
可以警报!
铁门是结实的
由此可以看出,由抽象类门定义出门的基本特点后由其子类实现,而每个子类各有各的实现方式,这就是面向对象的多态特性。
存在限制
由于继承特性,每个子类只能继承一个父类,导致了其应用的局限性。譬如,一个宝箱具有门的开关功能,同时也可以装饰有珠宝,可以存东西,这两样是宝箱的特有性质,如果再用一个抽象类将这两样性质装进去,难免小题大做。这就涉及到另一个可以实现多态性的工具——接口,下文再讲。