目录
一:多态
方法的多态性
主要有方法的重载和方法的覆写两种
方法的重载:同一个类中的方法名称,会根据参数的类型和参数个数的不同进行选择。
方法的覆写:父类和子类中相同名称的函数,根据实例化子类的对象去调用。
对象的多态性
父类和子类之间的对象的相互转换,可以类比基本类型的转换,比如int与double,double的范围大于int,int到double是自动完成的,但是double到int是强制完成的。
由于子类是继承父类基础上得到,所以 子类对象转换为父类对象是自动完成的
父类 父类对象=子类实例(自动转换) ,但是父类对象转变为子类对象却是强制的。
子类 子类对象=(子类)父类对象
但是向下转型有安全隐患:(大范围到小范围)
但是:可以把父类对象强制转换子类。
向上转型的目的:实现参数的统一
class A{
public void fun() {
System.out.println("A,fun()");
}
}
class B extends A{
public void fun() {
System.out.println("B,fun()");
}
}
class C extends A{
public void fun() {
System.out.println("C,fun()");
}
}
public class transfer {
public static void main(String[] args) {
/*A a1=new B();
A a2=new C();
a1.fun();
a2.fun();
四行代码可以统一为一个对象的调用函数*/
print(new B());
print(new C());
}
public static void print(A a) {
a.fun();
}
}
运行结果:B,fun()
C,fun()上图代码:采用向上转换(大范围到小范围即:父类->子类),调用所有子类的对象的方法却可以只用一个A类对象去作为参数的传递,极大提高了代码效率
向下转换的目的: 调用子类特别方法
class A{
public void fun() {
System.out.println("A,fun()");
}
}
class B extends A{
public void fun() {
System.out.println("B,fun()");}
public void acfun() {
System.out.println("B,acfun()");
}
}
public class transfer {
public static void main(String[] args) {
print(new B());
}
public static void print(A a) {//统一参数
/*强制把a类对象缩小为b,前提是:A a=new B()*/
B b=(B) a;//A a=new B(),虽说实例化B类,但是对象依然是A类,不能调用B的特有方法。
b.acfun();
}
}
总结:父类 父类对象=new 子类()后 ,对象可以调用父子同名的子类方法,但不可以调用子类新方法,想用就得把父类对象强制转换为子类对象。
关键字:instanceof
格式:对象 instanceof 类,返回布尔值:对象是不是在类中。
结论:父类 对象=new 子类(),这叫向下转型,对象即在父类又在子类,只不过只能调用和父类同名的重载方法。但是实例化子类对象,一定同时属于父类和子类,子类继承父类,其对象天然在父类。
instanceof作用:用于判断向下转型,避免异常
class A{
public void fun() {
System.out.println("A fun()");
}
}
class B extends A{
public void fun() {
System.out.println("B fun()");
}
public void acfun() {
System.out.println("B acfun()");
}
}
public class transfer {
public static void main(String[] args) {
print(new B());
}
public static void print(A a) {
if(a instanceof B) {
B b=(B) a;
b.acfun();
}
}
}
二:抽象类
抽象类要掌握:定义抽象类的语法,抽象类的使用限制。
抽象类的定义
普通类中:有属性,有构造方法,有普通方法,有static方法,而且可以直接实例化。
但是抽象类区别于普通类就是多了抽象方法,也就是没有方法体{}的方法。抽象方法要用abstract修饰,而且定义抽象方法的抽象类也要加abstract.
注意:抽象方法不能直接实例化,因为抽象类的抽象方法没有方法体,故而不可以去直接调用。
原则:抽象类必须有子类,也就是被子类继承,而且子类必须覆写抽象类的全部抽象方法。抽象类的对象实例化必须通过子类向上转型去完成。
abstract class A{
public abstract void fun() ;
//抽象方法:有abstract关键字,但是没有方法体{}
public abstract void print();
}
class B extends A{
//覆写抽象类全部抽象方法
public void fun() {
System.out.println("fun");
}
public void print() {
System.out.println("print");
}
}
public class transfer {
public static void main(String[] args) {
A a=new B();//向上转型 抽象类用子类实例化
a.print();
a.fun();
}
/*运行结果:
fun
print*/
注意:虽然普通类可以被继承,但实际开发,最好普通类只继承抽象类。
抽象类的相关限制
1:抽象类有属性,所以有可以初始化参数的构造方法。
注意:执行子类构造方法会执行父类的构造方法。
abstract class A{
private int num;
public A(int num) {//父类构造方法
this.num=num;
}
public int getNum() {
return this.num;
}
public abstract void fun() ;//抽采方法
}
class B extends A{
private String msg;
public B(int num,String msg){//子类构造方法
super(num);//调用父类传参
this.msg=msg;
}
public String getMsg() {
return this.msg;
}
//覆写抽象类全部抽象方法
public void fun() {
System.out.println("fun");
}
}
public class transfer {
public static void main(String[] args) {
B a=new B(9,"good");//向上转型 抽象类用子类实例化
a.fun();
System.out.println(a.getNum()+" "+a.getMsg());
}
}
2:由于抽象类必须要继承,而final类不可以继承,所以抽象类不可以加final;
3:就算抽象类没有抽象方法,也不可以在主程序中直接实例化。
4:抽象类与static用法。
1):外部类abstract不可以直接在前面用static修饰,但是可以在内部类叫static,此时抽象static类相当于外部抽象类。
abstract class A{
static abstract class B{//抽象类A的static内部类
public abstract void print();//A.B的抽象方法
}
}
class C extends A.B{//继承外部类.内部类
public void print() {//继承类覆写抽象方法
System.out.println("GOOD!");
}
}
public class transfer {
public static void main(String[] args) {
A.B ab=new C();//内部类B的向上转型
ab.print();
}
}
2):抽象类的static方法,可以不用子类继承直接通过:抽象类.方法去使用。
abstract class A{
public static void print() {//抽象类的具体static方法
System.out.println("GOOD!");
}
}
public class transfer {
public static void main(String[] args) {
A.print();//直接用类名去调用static方法
}
}
隐藏抽象类的子类
比如:抽象类A,子类B,实例化A需要:A 对象=new B();有点多余,想隐藏B。
abstract class A{
public abstract void print();//抽象类A的抽象方法
private static class B extends A{//继承类直接在抽象类中定义,用private去封装
public void print() {//B对A的方法覆写
System.out.println("HELLO");
}
}
//使用static原因:这个方法不受实例化对象控制
public static A getInstance() {//位置:在A类中B类外
return new B();
}
}
public class transfer {
public static void main(String[] args) {
A a=A.getInstance();
a.print();
}
}
或者直接写成: A.getInstance().print();
注意:static方法只能调用static类。
范类:继承子类的构造函数一定会调用父类的构造函数。
\