多态性+抽象类

141 阅读5分钟

目录

一:多态

       方法的多态性

       对象的多态性 

                 向上转型的目的:实现参数的统一

                  向下转换的目的: 调用子类特别方法

       关键字:instanceof

二:抽象类

        抽象类的定义

        抽象类的相关限制 

        隐藏抽象类的子类


一:多态

方法的多态性

主要有方法的重载和方法的覆写两种
方法的重载:同一个类中的方法名称,会根据参数的类型和参数个数的不同进行选择。
方法的覆写:父类和子类中相同名称的函数,根据实例化子类的对象去调用。

对象的多态性 

        父类和子类之间的对象的相互转换,可以类比基本类型的转换,比如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类。

 范类:继承子类的构造函数一定会调用父类的构造函数。

\