java基础--多态_抽象类

概念

多态性是面向对象编程的又一个重要特征,它是指在父类中定义的属性和方法被子类继承之后,可以具有不同的数据类型或表现出不同的行为,

对面向对象来说,多态分为编译时多态和运行时多态。

编译时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的方法。通过编译之后会变成两个不同的方法,在运行时谈不上多态。
运行时多态是动态的,它是通过动态绑定来实现的,也就是大家通常所说的多态性。

Java 实现多态有 3 个必要条件

继承、重写和向上转型。
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才既能可以调用父类的方法,又能调用子类的方法。


这里提一下向上转型和向下转型

向上转型

  1. 向上转型概念

隐式转型、自动转型,父类引用指向子类实例,小类转型为大类。
如 Animal two=new Dog();//Dog类是Animal类的子类
向上转型是安全的,任何子列都继承并接受了父类的方法,狗属于动物。但是向下转型不可以,不能说动物就是狗这是不成立的,(向下转型要通过强制类型转换)

  1. 应用:

    1)、当一个子列对象向上转型父类类型之后,就被当成了父类对象,能调用的方法会减少 可以调用子类重写父类的方法(此处调的是子类的方法)以及父类派生的方法,无法调用子类独有方法

    2)、父类中的静态方法无法被子类重写,
    例如父类的静态方法

		public static void say(){
	System.out.println("动物叫...");
}

子类中也有一个同名的静态方法,此时say()属于子类自己独有的方法,不构成重写(可以用@Override注解判断是否是重写)

public static void say(){
	System.out.println("小狗汪汪叫...");
}
 Animal two=new Dog();
 two.say();//此时调用的是父类静态方法say(),打印:动物叫...

所以向上转型之后,只能调用到父类原有的静态方法

多态的实现可以通过向上转型和动态绑定机制来完成,向上转型实现了将子类对象向上转型为父类对象类型,二动态绑定机制能识别对象转型前的类型,从而自动调用该类的方法,

扫描二维码关注公众号,回复: 8898639 查看本文章

动态绑定:
绑定就是将一个方法调用同一个方法所在的类连接到一起,绑定分为静态绑定和动态绑定两种。
静态绑定:在程序运行之前进行绑定(由编译器和链接程序完成)
例如:
Dog dog = new Dog();
dog.say();
这种调用在代码里指定,编译时编译器就知道调用dog类中的say()方法

动态绑定:在程序运行期间由JVM根据对象的类型自动的判断应该调用哪个方法,

Animal [] animals = new Animal[5];
for(int i = 0; i < animals.length; i++){
	int n = (int)(Math.random() *2);//随机产生0到1中的一个数
	switch (n){
		case 0:
			animals[i] = new Cat();
			break;
		case 1:
			animals[i] = new Dog();
			break;
	}
}

for (int i = 0; i < animals.length; i++){
	animals[i].eat();
}

在编译过程中不知道调用哪个类的eat()方法,直到运行时才能到底调用哪个类的eat方法,这种就是动态绑定
--------------------------------------------------

向下转型

子类引用指向父类对象,需要强制类型转换
如:

Animal two=new Dog();
Dog dog = (Dog)two;//此处必须进行强制类型转换

向下转型后,可以调用子类特有的方法

但是必须满足转型条件才能进行强转

Animal animal = new Dog();
Dog dog = (Dog) animal;  //正确写法
Cat cat = (Cat) animal;  //这种写法不正确,编译报错Exception in thread "main" java.lang.ClassCastException: com.imooc.animal.Dog cannot be cast to com.imooc.animal.Cat

这个时候可以用instanceof运算符进行判断:返回true/false

Animal animal = new Dog();
if (animal instanceof Dog) {
	Dog dog = (Dog) animal;
	System.out.println("dog...");
}else if (animal instanceof  Cat){
	Cat cat = (Cat) animal;
	System.out.println("cat...");
}

抽象类和抽象方法

1. 概念

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。抽象方法也是同一个道理。
使用abstract class来定义抽象类
例如:

//抽象类:不允许实例化,可以通过向上转型,指向子类实例
public abstract class Animal {
	
	public Animal(){	
	}
	//抽象方法:不允许包含方法体;子类中需要重写父类的抽象方法,否则,子类也是抽象类
	//static final private不能与abstract并存
	public abstract void eat();
	}

2. 特点:

1.抽象方法不能被直接实例化
它只能作为其他类的父类,但可以向上转型,指向实例化

//Animal是抽象类的错误示范:
Animal Animal  = new Animal();//直接new是错误的

2.抽象方法只有声明,不能有实现。
例如:

public abstract void eat();

3. 意义:

为其子类提供一个公共的类型。
封装子类中的重复内容(成员变量和方法)
将父类设计成抽象咧后,即可借由父子继承关系限制子类设计随意性,在一定程度上避免了无父类的实例化

4. 重点:

1.含有抽象方法的类,只能被定义成抽象类
在这里插入图片描述
正确的写法
在这里插入图片描述
2.抽象类不一定包含抽象方法
3.在抽象类中的成员方法可以包括一般方法和抽象方法
4.抽象类不能被实例化,即使抽象类中不包含抽象方法,这个抽象咧也不能创建实例。抽象类的构造方法主要是用于被其子类调用
5.一个类继承抽象类后,必须实现其所有抽象方法,否则也是抽象类,不同子类对父类的抽象方法可以有不同的实现。
6.即使父类是具体的,但其子类也可以是抽象的,如object类是具体的类,但是可以创建抽象子列
7.abstract方法不能用static和private修饰,
对于类,不能同时用final和abstract修饰,因为final关键字使得类不可继承,而abstract修饰的类如果不可以被继承将没有任何意义。

发布了33 篇原创文章 · 获赞 7 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/shunli008/article/details/101604142
今日推荐