java三大特性之多态
一:概念
对象的多种形态。
二:分类
1:引用多态:父类的引用可以指向本类的对象,父类的引用可以指向子类的对象
//父类
public class Animal{}
//子类
public class Dog extends Animal{}
//测试类
public static void main(String[] args) {
Animal obj1=new Animal(); //父类的引用指向本类的引用
Animal obj2=new Dog();//父类的引用指向子类的引用
//Dog dog=new Animal();//子类的引用不能指向父类
}
}
2:方法多态:创建本类对象时,调用的方法为本类方法。创建子类对象时,调用的方法为子类重写的方法或继承的方法
public class Animal {
public void eat(){
System.out.println("动物具有吃的能力");
}
}
public class Dog extends Animal{
public void eat(){
System.out.println("狗是吃肉的");
}
}
public class Cat extends Animal{}
public class Init {
public static void main(String[] args) {
Animal obj1=new Animal(); //父类的引用指向本类的引用
Animal obj2=new Dog();//父类的引用指向子类的引用
Animal obj3=new Cat();
//Dog dog=new Animal();//子类的引用不能指向父类
obj1.eat();//调用的是父类的eat()方法
obj2.eat();//调用的是子类的eat()方法
obj3.eat();
}
}
运行结果为:
这里有一个需要特别注意的!!
如果子类里面有一个自己的方法是父类的没有的,那么就不能通过父类的引用指向子类的引用创建的对象来调用该方法!。
三:引用类型转换
1:向上类型转换(隐式/自动类型转换),是小类型到大类型的转换
2:向下类型转换(强制类型转换),是大类型到小类型
用instanceof运算符,来解决引用对象的类型,避免类型转换的安全性问题
//父类
public class Animal {
public void eat(){
System.out.println("动物具有吃的能力");
}
}
//子类
public class Dog extends Animal(){}
public class Cat extends Animal(){}
//测试类
public class Init {
public static void main(String[] args) {
Dog dog=new Dog();
Animal animal=dog;//向上类型转换/自动转换
if(animal instanceof Dog){
Dog dog2=(Dog)animal;//向下类型转换,强制转换
}else{
System.out.println("不能进行类型转换,转换为Dog类型");
}
if(animal instanceof Cat){
Cat cat=(Cat)animal; //编译时指向的Cat型,实际运行的时候animal是指向Dog型的
}else{
System.out.println("不能进行类型转换,转换为Cat类型");
}
}
}
四:抽象类
类前面会用abstract关键字修饰
1):在以下场景会用到抽象类:
1:在某些情况下,某个父类只是知道其子类应该包含怎样的方法,但无法准确知道这些子类如何实现这些方法
2:从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为子类模板,从而避免了子类设计的随意性
2):使用规则:
1:abstract定义抽象类
2:abstract定义抽象方法,只有声明,不需要实现
3:包含抽象方法的类是抽象类
4:抽象类中可以包含普通方法,也可以没有抽象方法
5:抽象类不能直接创建,可以定义引用变量。
3):特点
1:抽象类不仅含有抽象方法,也可以由普通的方法
2:抽象方法只能是public 和 protected,因为抽象类是用来被继承的,private方法无意义
3:抽象类不能用来被创建对象,他是用来被继承的
4:一个子类继承了抽象类必须要实现抽象类的抽象方法,否则这个子类也是抽象类。
public abstract class Shape { //抽象类,其中面积和周长是抽象方法
float radius;
public abstract double circumference(float radius);
public abstract double area(float radius);
}
public class Square extends Shape {
@Override
public double circumference(float width) {
return width*4;
}
@Override
public double area(float width) {
return width*3.14*width;
}
}
public class Circle extends Shape {
@Override
public double circumference(float radius) {
return 2*3.14*radius ;
}
@Override
public double area(float radius) {
return 3.14*radius*radius;
}
}
public class Test {
public static void main(String[] args) {
Shape square=new Square();
Shape circle=new Circle();
float radius=3.0f;
System.out.println("正方形的周长为:"+square.circumference(radius)+"正方形的面积为:"+square.area(radius));
System.out.println("圆形的周长为:"+circle.circumference(radius)+"圆形的面积为:"+circle.area(radius));
}
}
五:接口
接口可以理解为一种特殊的类,由全局变量和公共的抽象方法所组成。
1:语法规则:
[修饰符]interface 接口名 [extends 父接口1,父接口2...]
{
零个到多个常量定义...
零个到多个抽象方法定义...
}
接口就是用来被继承,被实现的,修饰符一般建议用public。注意:不能用private和protected修饰接口
2:接口定义:
a:常量:接口中的属性是常量,即使定义时不添加public static final 修饰符,系统也会自动加上。
b:方法:接口中的方法只能是抽象方法,总是使用,即使定义时不添加public abstract 修饰符,系统也会自动添加。
3:接口的使用
一个类可以实现一个或多个接口,实现接口使用implements关键字。java中一个类只能继承一个父类,是不够灵活的,通过实现多个接口可以做补充
[修饰符] class 类名 extends 父类 implements 接口1,接口2...
{
类体部分//如果继承了抽象类,需要实现继承的抽象方法;需要实现接口中的抽象方法
}
//抽象类
public abstract class Telphone {
public abstract void call();
}
//接口类
public interface IPlayGame {
public void playGame();
}
//继承与抽象类的smartPhone类,同时实现接口IplayGame
public class smartPhone extends Telphone implements IPlayGame {
@Override
public void call() {
System.out.println("智能机用屏幕打电话");
}
@Override
public void playGame() {
System.out.println("智能机可以打电话");
}
}
//类PsGame实现接口IPlayGame
public class psGame implements IPlayGame {
@Override
public void playGame() {
System.out.println("Ps机也可以打游戏");
}
}
//测试类
public class Test {
public static void main(String[] args) {
Telphone smartphone=new smartPhone();
IPlayGame ps=new psGame();
smartphone.call();
ps.playGame();
IPlayGame ps1=new psGame(){
@Override
public void playGame(){
System.out.println("通过匿名方法来实现接口");
}
};
ps1.playGame();
new psGame(){
@Override
public void playGame(){
System.out.println("通过匿名内部类的方法来实现接口1");
}
}.playGame();
}
}
运行结果为:
五:抽象类和接口的区别:
1):抽象类可以有构造方法,但是接口中不能有构造方法
2):抽象类中可以有普通成员,接口中的变量都是用public static final来修饰的
3):抽象类中可以有普通方法,接口中的方法都是用public abstract来修饰的
4):抽象类中可以有静态方法,接口中不含有静态方法
5):一个类可以实现多个接口,但是只能继承一个抽象类