父类变量引用子类对象
- 我们知道C++中用父类的指针和引用指向子类对象,从而实现多态,但是Java中没有指针,引用也和C++不同。
- Java中的父类变量引用子类对象格式:Base b = new Derived(参数表)
例如:Shape C1 = new Circle(5);
抽象类和抽象函数
- 抽象类的定义方法是在class前加关键字abstract,抽象函数是在返回值前加关键字abstract。
- Java的抽象类规则和C++一样,主要有:
- 抽象类不存在对象
- 有抽象函数的类就是抽象类(所以类名和函数名前都要加abstract)但是抽象类不一定要有抽象函数。
- 继承抽象类的子类,如果想成为非抽象类,必须覆盖所有抽象函数。
abstract class Beverage {
public final void prepareRecipe() {
boilWater();
brew();
pourInCup();
System.out.println(type()+"已经准备好了,请享用!");
} //整合每个步骤的虚函数
public void boilWater() { System.out.println("热水已经烧好了!"); }
public abstract void brew();
public void pourInCup() {
System.out.println(type() + "已经倒到杯子里了!");
}
public abstract String type();
}
class Tea extends Beverage {
public void brew() { System.out.println("将茶叶放到热水里");}
public String type() { return "茶"; }
}
class Coffee extends Beverage {
public void brew() { System.out.println("将咖啡放到热水里"); }
public String type() { return "咖啡"; }
}
public class Main {
public static void main(String[] args) {
Beverage b = new Coffee();
b.prepareRecipe();
b = new Tea();
b.prepareRecipe();
}
}
由这个例子,我们可以看出:当一个任务需要很多步骤完成,每个步骤有着不同的子类时,我们可以分别定义虚函数,再将虚函数整合到一个函数中。
接口
接口的概念
- Java中的接口类似于C++中的纯虚类,来描述某个类所支持的操作,这些操作只有方法声明,没有具体实现,所有方法均为抽象方法。
- 方法的具体实现在实现这个接口的类中完成。
接口的定义
-
定义格式:
修饰符 接口名 extends 接口名 {
public static final 数据类型 常量名 = 常量数据;
publlic abstract 方法类型 方法名( [参数] )
} - public是接口唯一访问控制修饰符,如果没有使用任何访问修饰符,表示只有与该接口在同一个包中的类或接口才可以访问这个接口。
- 接口支持多重继承
- 接口中定义常量和方法前的修饰语唯一,因此可以省略关键字。
- 接口中定义的常量可以在使用接口的类中使用。如果类中重新定义同名变量则覆盖接口变量,想要引用接口变量,需要用 接口名.变量名
接口实现
-
格式:
修饰符 class 类名 implements 接口名1,接口名2, … - 非抽象类在实现接口时,在类中必须对接口中的所有方法给出具体体现。
- 在接口中声明方法时,可以省略public和abstract关键字,类在实现接口时,一定要有public来修饰。
- 接口也是一种引用类型,用接口实现多态的方法是:声明接口类型的指针指向拥有接口的类。
interface Shape {
double pi = 3.14;
void setColor(String str);
}
interface Shape2D extends Shape {
double area();
}
class Circle implements Shape2D {
double radius;
double pi = 1; //覆盖Shape2D中的pi
String color;
public Circle(double r) { radius = r; }
public double area() { return (Shape2D.pi*radius*radius); } //使用Shape2D中的pi
public void setColor(String str) { color = str; System.out.println("color="+color);}
}
public class Main {
public static void main(String[] args) {
Shape2D circle = new Circle(5);
circle.setColor("blue");
System.out.println("Area="+circle.area());
}
}
多态
- 在Java中,我们有和C++中相同的多态方法:即用父类指针指向子类对象。
- Java中有一个特殊的接口类。需要特别说明的是与接口有关的多态性。之前已经提到可以用接口引用指向类,其实接口可以看成特殊的类,我们可以在类中定义一个接口成员,指向使用接口的类。
interface PCI {
String show();
void operate();
}
class NetWorkCard implements PCI {
public String show() { return "网卡"; }
public void operate() { System.out.println("我在传输网络数据"); }
}
class SoundCard implements PCI {
public String show() { return "声卡"; }
public void operate() { System.out.println("我在播放声音"); }
}
class MotherBoard {
PCI pci;
MotherBoard() { System.out.println("我是主板"); }
void plugin(PCI in) { pci = in; System.out.println(in.show()+"插入到PCI插槽中"); }
void operate() { pci.operate(); }
}
public class Main {
public static void main(String[] args) {
MotherBoard m = new MotherBoard();
m.plugin(new NetWorkCard());
m.operate();
m.plugin(new SoundCard());
m.operate();
}
}
instanceof
用法:a instanceof A
a为某对象名,A为类名或接口名,返回boolean,当a是类A的对象,或a是类A子类的对象,或a所属的类包含接口A时,返回true。
getClass( )
getClass( )是Object类的方法,当要判断a是否就是类A的对象时,要用:
a.getClass( ) == A.class;
interface Print {
void print();
}
class Base implements Print{
int x;
public Base(int xx) { x = xx; }
public void print() { System.out.println(x); }
}
class Derived extends Base {
public Derived(int x) { super(x); }
}
public class Main {
public static void main(String[] args) {
Derived D = new Derived(5);
System.out.println(D instanceof Base);
System.out.println(D instanceof Derived);
System.out.println(D instanceof Print);
System.out.println(D.getClass() == Derived.class);
// System.out.println(D.getClass() == Base.class); 会报错
Base B = new Derived(5);
System.out.println(B.getClass() == Derived.class);
System.out.println(B.getClass() == Base.class);
}
}
除最后一个为false以外,其他均为true