多态 抽象方法

多态

实际意义:

屏蔽不同子类的差异性 实现通用的编程 带来不同的结果

public class ShapeTest {
    //打印矩形
//    public static void draw(Rect r){
//        System.out.println(r.toString());
//    }
//    //打印圆形
//    public static void draw(Circle r){
//        System.out.println(r.toString());
//    }
    public static void draw(Shape u){
        System.out.println(u.toString());

    }
    public static void main(String[] args) {
    ShapeTest.draw(new Rect(17,18,19,20));
    ShapeTest.draw(new Circle(21,22,23));
    }
}

同一种事物的多种形态

父类类型的引用指向子类类型的对象

父类类型 引用变量名 = new 子类类型();

向上转型:可以把不同的子类对象都当作父类来看,进而屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,统一调用标准。
比如:父类Parent,子类Child
父类的引用指向子类对象:Parent p=new Child();
说明:向上转型时,子类对象当成父类对象,只能调用父类的功能,如果子类重写了父类中声明过的方法,方法体执行的就是子类重过后的功能。但是此时对象是把自己看做是父类类型的,所以其他资源使用的还是父类型的。
比如:花木兰替父从军,大家都把花木兰看做她爸,但是实际从军的是花木兰,而且,花木兰只能做她爸能做的事,在军营里是不可以化妆的。

eg:

Shape sr = new Recy();

sr.show;

当父类类型的引用指向子类类型的对象时,父类类型的引用可以直接调用父类独有的方法。
当父类类型的引用指向子类类型的对象时,父类类型的引用不可以直接调用子类独有的方法。
对于父子类都有的非静态方法来说,编译阶段调用父类版本,运行阶段调用子类重写的版本(动态绑定)
对于父子类都有的静态方法来说,编译和运行阶段都调用父类版本。(静态方法的调用 只取决于这个变量所隶属于的类型,跟指向的对象没有关系,跟是否创建对象无关)(/*多态中,调用的静态方法是父类的,因为多态对象把自己看作是父类类型 * 直接使用父类中的静态资源*/)

public class ShapeRectTest {
    public static void main(String[] args) {
        //声明Shape类型的引用指向shape类型的对象并打印特征
        Shape shape = new Shape(1,2);
        String s = shape.toString();
        System.out.println(s);
        Rect rect = new Rect(3, 4, 5, 6);
        String s1 = rect.toString();
        System.out.println(s1);
/*--------------------------------------------------------------------------*/
//当父类的方法不满足子类的需求 需要重写
        //声明rect类型的引用指向rect类型的对象并打印特征
        //声明shape类型的引用指向rect类型的对象并打印
        //向上转型? 应用之类的需要了解 效果不清楚
        //披着父类的子类
        Shape sr= new Rect(7,8,9,10);
        String s2 = sr.toString();
        System.out.println(s2);
        //在编译阶段调用父类的方法 在运行阶段调用子类rect的tostring方法
    //shape父类的引用能不能直接调用父类和子类独有的方法
        int x = sr.getX();
        System.out.println(x);
        //披着父类的子类 可以直接调用父类的方法
        //sr.getl(); 不能调用子类的方法
        //共同的方法 编译调父类 运行调子类
        sr.test();//隶属于类层级
        shape.test();
        //编译阶段和运行阶段都是调用的父类
        int l = ((Rect) sr).getL();//强转
               System.out.println("披着父类的子类获取到的长度"+l);
        //希望将shape父类型转换为rect子类型
        //String str1 = (String)sr;
        //Inconvertible types; cannot cast 'night.Shape' to 'java.lang.String'
        Shape qiangzhuan = (Shape) rect;
        String s3 = qiangzhuan.toString();
        System.out.println("强转之后的属性:"+s3);
        System.out.println(s1);
    }
}

 

父类:

public class Shape {
    private int x;
    private int y;
    public static void test(){
        System.out.println("父类中的静态方法");
    }
    public Shape(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public Shape() {

    }

    @Override
    public String toString() {
        return "Shape{" +
                "x=" + x +
                ", y=" + y +
                '}';
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getX() {
        System.out.println("父类中的独有方法");
        return x;
    }

    public int getY() {
        return y;
    }
}

子类:
 

public class Rect extends Shape{
    private int w;
    private int l;

    public static void test(){
        System.out.println("子类中的静态方法");
    }

 参考一下这位博主的 理解更透彻 
特别是其说法 编译看左边 运行看右边
多态

  1. 成员变量: 使用的是父类的(编译)
  2. 成员方法: 由于存在重写现象,所以使用的是子类的(运行)
  3. 静态成员: 随着类的加载而加载,谁调用就返回谁的(什么叫做谁调用)

引用数据类型之间的转换

1.引用数据类型之间的转换方式有两种:自动类型转换和强制类型转换,
2.自动类型转换主要指小类型向大类型的转换,也就是子类转为父类,也
叫做向上转型。
3.强制类型转换主要指大类型向小类型的转换,也就是父类转为子类,也
叫做向下转型或显式类型转换。
4..引用数据类型之间的转换必须发生在父子类之间,否则编译报错。

instanceof

做强转之前做一个判断 防止向上转型这种只是编译过了

if(sr instanceof Circle){
            System.out.println("可以放心转换");
        }
        else{
            System.out.println("强转有风险 操作需谨慎");
        }


抽象方法

abstract

方法没法直接写 需要在具体子类里重写 先声明

public abstract void cry(); 

抽象类

1.不能具体实例化 不能创建对象

2.abstract和private 不能共同修饰同一个方法 因为私有方法不能被继承

3.final和abstract不能共同修饰同一个方法

4.static同上 static理解为共享

public abstract class AbstractTest {
    private int cnt;

    public AbstractTest() {
    }

    public AbstractTest(int cnt) {
        this.cnt = cnt;
    }

    public void setCnt(int cnt) {
        this.cnt = cnt;
    }

    public int getCnt() {
        return cnt;
    }
    public  abstract  void show();

    public static void main(String[] args) {
        //AbstractTest abstractTest = new AbstractTest();

    }
}

抽象类默认要有抽象方法

规定抽象类不能声明对象 就是为了防止通过抽象类对象调用抽象方法

抽象类的实际意义

继承抽象类必须要重写其抽象方法

或者自己也还是抽象类

多态的使用场景一是形参通用

多态的使用场景二:

public class SubAbstractTest extends AbstractTest {
    public static void main(String[] args) {
        //AbstractTest abstractTest = new AbstractTest();
        SubAbstractTest sat = new SubAbstractTest();
        SubAbstractTest at = new SubAbstractTest();
        //
    }
    @Override
    public void show() {
        System.out.println("被迫重写");
    }
}

在以后的开发中推荐使用多态的格式,此时父类类型引用直接调用的所有方法一定是父类中拥有的方法,若以后更换子类时,只需要将new关赞字后面的子类类型修改而其它地方无需改变就可以立即生效,从而提高了代码的可维护性和可扩展型。

抽象类:

public abstract class Account {
    private double money;
    //子类通过super调用
    public void setMoney(double money) {
        this.money = money;
    }

    public double getMoney() {
        return money;
    }

    public Account(double money) {
        this.money = money;
    }

    public Account() {
    }

    public abstract double getLixi();
}
public class FixedAccoount extends Account{

    public FixedAccoount(int i) {
        super(i);//调用父类的有参构造
    }

    public FixedAccoount() {
        super();
    }

    @Override
    public double getLixi() {
        return getMoney() * 0.03*1;
    }

    public static void main(String[] args) {
//        Account fixedAccoount = new FixedAccoount(1000);
        FixedAccoount fixedAccoount = new FixedAccoount();
        fixedAccoount.setMoney(1000);
        double lixi = fixedAccoount.getLixi();
        System.out.println(lixi);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值