* 多态: 父类的 引用变量 指向了子类的对象
或者
* 接口的 引用变量 指向了接口实现类对象
* 多态前提:必须存在 继承或者 实现关系
* 多态要注意的细节:
* 1.多态情况下,子父类 存在 同名的成员变量(包括 非静态和 静态),默认 访问父类的成员变量
* 2.多态情况下,子父类 存在 同名的非静态函数时,默认的是 子类的成员函数
* 3.多态情况下,子父类 存在 同名的静态函数时,默认访问的父类的成员函数
* 4.多态情况下,不能访问 子类 特有的成员
* 总结: 对于 同名 子父类的成员,只有 非静态的成员方法,访问的是 子类 ,其他的访问的都是父类
/*
* 需求:定义一个图形,矩形,圆形 三个雷,所有的图形都具备计算 面积和周长的方法
*
* 要求:
* 1.定义一个方法 可以接受 任意类型的图形对象,
* 在该方法内部 调用 图形的周长和面积的方法
*
* 2.定义一个方法 ,可以返回 任意类型的图形对象
*
* */
abstract class Shape{
public abstract double getArea();
public abstract double getLength();
}
//单继承: java是单继承的,一个类 最多 只能有一个 直接父类
//(一种事物 只能够 是属于 唯一的另一种事物)
class Rect extends Shape{
double width;
double height;
public Rect(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double getArea() {
return width*height;
}
@Override
public double getLength() {
return 2*(width+height);
}
}
class Circle extends Shape{
public static final double PI = 3.14;
double r;
public Circle(double r) {
super();
this.r = r;
}
@Override
public double getArea() {
// TODO Auto-generated method stub
return PI*r*r;
}
@Override
public double getLength() {
// TODO Auto-generated method stub
return 2*PI*r;
}
}
public class Demo1 {
public static void main(String[] args) {
Rect r = new Rect(2.0, 3.0);
Circle c = new Circle(3.0);
//定义一个方法 print。具备多种重载方式,打印传进去的各种图形的周长和面积
//print(r);
//print(c);
//但是 ,我们希望在一个方法中 实现 (使用多态)
Shape s1 = new Rect(3.0, 4.0);
Shape s2 = new Circle(4.0);
print(s1);
print(s2);
//Shape s3 = getShape(1);
//Shape s4 = getShape(-1);
//强制类型转换
Rect r2 = (Rect)getShape(1);
Circle c2 = (Circle)getShape(-1);
}
//多态的用法:
//父类类型 可以 作为 方法的返回值,具体返回的类型可以是 任意 子类类型
//定义一个方法,可以返回任意类型的图形对象
public static Shape getShape(int i){
//通过i的 值来返回
if(i>0){
return new Rect(4.0, 5.0);
}else{
return new Circle(4.0);
}
}
//多态的作用:
//父类可以作为方法的参数类型,具体 传进方法的参数 可以是 任意 子类类型
//定义一个方法,可以接受 任意类型的图形对象
private static void print(Shape s) {
/*
传进去的 s 是一个 父类的显式类型(编译时类型),
如何知道 到底是 什么 实际类型(运行时类型)?
*/
String shapeName = "";
if(s instanceof Rect){
shapeName = "矩形";
}else if(s instanceof Circle){
shapeName = "圆形";
}
System.out.println(shapeName+"的面积:"+s.getArea());
System.out.println(shapeName+"的周长:"+s.getLength());
}
/*
private static void print(Circle c) {
System.out.println("圆形的周长为:"+c.getLength());
System.out.println("圆形的面积为:"+c.getArea());
}
private static void print(Rect r) {
System.out.println("矩形的周长为"+r.getLength());
System.out.println("矩形的面积为"+r.getArea());
}*/
}
多态情况下,不能访问子类特有的成员
多态 情况下,如果需要 调用到子类 特有的成员,那么需要进行 强制类型转换
* 基本数据类型:
* 小数据类型->大数据类型: 自动类型转换
* 大数据类型->小数据类型: 强制类型转换
* 引用数据类型转换
* 子类数据类型->父类数据类型: 自动类型转换
* 父类数据类型->子类数据类型: 强制类型转换
* ClassCastException:强制类型转换异常
* 在转换之前 一般 使用 instanceof关键字 先判断
class A{
int a = 10;
}
class B extends A{
int b = 20;
}
class C extends A{
}
public class Demo2 {
public static void main(String[] args) {
A a = new B(); //自动类型转换
//将 父类 的 类型 转换为 子类的类型(大转小:强转)
B b = (B) a; //强制类型转换
//C c = (C) a; //ClassCastException
System.out.println("a属于 B类型:"+(a instanceof B));
System.out.println("a属于 C类型:"+(a instanceof C));
System.out.println(b.b);
}
}
实现关系下的多态:接口的引用 类型变量 指向了 接口实现类的对象
* 接口中的方法 全部 是 非静态。多态情况下, 子父类 存在同名的非静态函数时,
* 默认是访问子类的非静态函数
interface Dao{
/*
* 接口中的方法 全部 是 非静态。多态情况下, 子父类 存在同名的非静态函数时,
* 默认是访问子类的非静态函数
*
* */
void add(String user);
}
class UserDao implements Dao{
@Override
public void add(String user) {
// TODO Auto-generated method stub
System.out.println("添加用户"+user+"成功");
}
}
public class Demo3 {
public static void main(String[] args) {
Dao d = new UserDao(); //实现关系下的多态
d.add("张三");
}
}