[Java] 多态和接口
1. 多态
将一个方法调用同一个方法主体关联起来被称作绑定。若在程序执行前进行绑定,叫做前期绑定,比如C只有一种方法调用,就是前期绑定。而运行时根据对象的类型进行绑定,叫后期绑定。后期绑定也称做动态绑定或运行时绑定。Java中除了static方法和final方法之外,其他所有的方法都是后期绑定,这意味着它会自动发生,例如:
class Shape {
void draw() {
}
void erase() {
}
}
class Circle extends Shape {
void draw() {
}
}
class Square extends Shape {
void draw() {
}
}
public class Main {
public static void main(String[] args) {
Shape s = new Circle();
s.draw();
}
}
这里创建了一个Circle对象,并把得到的引用赋值给Shape,这是可以的,因为通过继承,Circle就是一种Shape。这时调用方法draw(),由于后期绑定(多态),还是正确调用了Circle.draw()方法。只有非private方法才可以被覆盖,因为private方法被自动认为是final方法,而且对导出类是屏蔽的,例如:
public class Shape {
private void draw() {
System.out.println("private");
}
public static void main(String[] args) {
Shape s = new Circle();
s.draw(); // private
}
}
class Circle extends Shape {
public void draw() {
System.out.println("public");
}
}
只有普通的方法调用是可以是多态的,如果直接访问某个域,这个访问将在编译期进行解析,例如:
class Super {
public int field = 0;
public void getField() {
System.out.println(field);
}
}
class Sub extends Super {
public int field = 1;
public void getField() {
System.out.println(field);
}
public void getSuperField() {
System.out.println(super.field);
}
}
public class Main {
public static void main(String[] args) {
Super sup = new Sub();
System.out.println(sup.field); // 0
sup.getField(); // 1
Sub sub = new Sub();
System.out.println(sub.field); // 1
sub.getField(); // 1
sub.getSuperField(); // 0
}
}
2. 抽象
Java提供了一个叫做抽象方法的机制,仅有声明而没有方法体,采用的语法如下:
abstract void f();
包含抽象方法的类叫抽象类,如果一个类包含一个或多个抽象方法,类必须被限定为抽象的。如果从一个抽象类继承,并想创建该类的对象,那么就必须为基类中的所有抽象方法提供方法定义,否则导出类也是抽象类,且编译器会强制要求用abstract关键字来限定这个类,例如:
abstract class Test1 {
public abstract void f();
public void print() {
System.out.println("Hello World!");
}
}
class Test2 extends Test1 {
public void f() {
System.out.println("Description");
}
}
public class Main {
public static void main(String[] args) {
Test2 t = new Test2();
t.print();
t.f();
}
}
3. 接口
interface关键字使抽象的概念更向前迈进了一步,abstract关键字允许在类中创建一个或多个没有任何定义的方法,interface关键字产生一个完全抽象的类,它没有任何相应的具体实现,它允许创建者确定方法名、参数列表和返回类型,但是没有任何方法体。
要想创建一个接口,需要用interface关键字来替代class关键字,可以在interface关键字前添加public关键字,如果不添加public关键字,则它只具有包访问权限。接口也可以包含域,但是这些域隐式地是static和final的。要让一个类遵循某个特定接口,需要使用implements关键字,除此之外,看起来很像继承。可以选择在接口中显式地将方法声明为public的,但即使不这么做,它们也是public的,因此当要实现一个接口时,在接口中被定义的方法必须被定义为public,例如:
interface Test1 {
public void f();
}
class Test2 implements Test1 {
public void f() {
System.out.println("Hello World!");
}
}
public class Main {
public static void main(String[] args) {
Test2 t = new Test2();
t.f();
}
}
4. 多重继承
在C++中,组合多个类的接口的行为被称作多重继承,它可能会带来沉重的包袱,因为每个类都有一个具体实现,在Java中,可以执行相同的行为,但是只有一个类可以有具体实现。在导出类中,不强制要求必须有一个是抽象的或没有任何抽象方法的基类,如果要从一个非接口的类继承,那么只能从一个类去继承,其余的基元素都必须是接口。需要将所有的接口名都置于implements关键字之后,用逗号将它们一一隔开,例如:
interface CanFight {
void fight();
}
interface CanSwim {
void swim();
}
interface CanFly {
void fly();
}
class ActionCharacter {
public void fight() {}
}
class Hero extends ActionCharacter implements CanFight, CanSwim, CanFly {
public void swim() {}
public void fly() {}
}
public class Main {
public static void main(String[] args) {
Hero h = new Hero();
h.fight();
h.swim();
h.fly();
}
}
5. 嵌套接口
接口可以嵌套在类或其他接口中,例如:
class Test {
interface I {
void f();
}
public class A implements I {
public void f() {}
}
public class B implements I {
public void f() {}
}
}
在类中嵌套接口的语法就像非嵌套接口一样,可以拥有public和包访问两种可视性,另外作为一种新添加的方式,接口也可以被实现为private(相同的语法即适用于嵌套接口,也适用于嵌套类)。
转载于:https://blog.51cto.com/hanviseas/1398728
上一篇: 干货 网站被降权了,怎么补救
下一篇: 分享网站降权处理经验