Com.Java.Basis第十一课 《抽象+多态》(一)

简介: Com.Java.Basis第十一课 《抽象+多态》(一)

第十一课 《抽象+多态》

第一部分:

Java的抽象:Java语言中,用abstract 关键字来修饰一个类时,这个类叫作抽象类。抽象类是它的所有子类的公共属性的集合,是包含一个或多个抽象方法的类。抽象类可以看作是对类的进一步抽象。在面向对象领域,抽象类主要用来进行类型隐藏。

特点:

1)抽象类,其修饰符必须为public或者protected,不能是private,因为创建抽象类,就是要被其他类继承,用private修饰了,则不能被子类继承,子类便无法实现该方法。


2)抽象类不能用来创建对象,即抽象类不能被直接实例化,要通过其普通子类进行实例化。


3)如果一个普通子类继承于一个抽象父类,则该类一定要重写实现该父类的抽象方法。如果该子类仍然是一个抽象类,这也是允许的,就不必重写实现该父类的抽象方法,但必须用abstract修饰。


4)抽象级别:抽象类是对整体类的抽象,包含属性和方法。


5)实现类的范围不同:抽象类,其实是从子类中提取共性部分,然后抽象出来,反之,子类继承该父类就可以了,也就是说里面的抽象方法一般来自同一个类别。


6)设计方式不同:抽象类是要先有子类,然后才抽象出父类,是一种从下往上的构建法则。

注意:

1、凡是用abstract修饰符修饰的类被称为抽象类。凡是用abstract修饰符修饰的方法称为抽象方法。


2、抽象类中可以有零个或多个抽象方法,也可以包含非抽象的方法。·抽象类中可以没有抽象方法,但是,有抽象方法的类必须是抽象类。


3、对于抽象方法来说,在抽象类中只指定其方法名及其类型,而不书写其实现代码。


4、抽象类可以派生子类,在抽象类派生的子类中必须实现抽象类中定义的所有抽象方法。


5、抽象类不能创建对象,创建对象的工作由抽象类派生的子类来实现。


6、如果父类中已有同名的abstract方法,则子类中就不能再有同名的抽象方法。


7、abstract不能与final并列修饰同一个类。


8、abstract 不能与private、static、final或native并列修饰同一个方法。

第二部分:Java的多态:

 

多态性是对象多种表现形式的体现。

现实中,比如我们按下 F1 键这个动作:

  • 如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;
  • 如果当前在 Word 下弹出的就是 Word 帮助;
  • 在 Windows 下弹出的就是 Windows 帮助和支持。

同一个事件发生在不同的对象上会产生不同的结果。


多态的优点

  • 1. 消除类型之间的耦合关系
  • 2. 可替换性
  • 3. 可扩充性
  • 4. 接口性
  • 5. 灵活性
  • 6. 简化性


多态存在的三个必要条件

  • 继承
  • 重写
  • 父类引用指向子类对象:Parent p = new Child();




第三部分:九个案例实操带你深入了解多态:

案例一:

从下面案例可知,A是抽象的,无法直接进行实例化操作。为什么不能直接实例化呢?

当一个类实例化之后,就意味着这个对象可以调用类中的属性或者放过了,但在抽象类里存在抽象方法,

而抽象方法没有方法体,没有方法体就无法进行调用。既然无法进行方法调用的话,又怎么去产生实例化对象呢。

package com.JavaBasicsDemo6.Abstract;
abstract class A {
    public void fun(){//普通方法
        System.out.println("存在方法体的方法");
    }
    public abstract void print();
    public static class TestDemo {
        public static void main(String[] args) {
//            A a = new A();
        }
    }
}

案例二

现在就可以清楚的发现:

(1)抽象类继承子类里面有明确的方法覆写要求,而普通类可以有选择性的来决定是否需要覆写;

(2)抽象类实际上就比普通类多了一些抽象方法而已,其他组成部分和普通类完全一样;

(3)普通类对象可以直接实例化,但抽象类的对象必须经过向上转型之后才可以得到。

虽然一个类的子类可以去继承任意的一个普通类,可是从开发的实际要求来讲,普通类尽量不要去继承另外一个普通类,而是去继承抽象类。

package com.JavaBasicsDemo6.Abstract1;
abstract class A{//定义一个抽象类
    public void fun(){//普通方法
        System.out.println("存在方法体的方法");
    }
    //抽象方法,没有方法体,有abstract关键字做修饰
    public abstract void print();
    public abstract void sleep();
    public abstract void height();
    public abstract void weight();
    public abstract void name();
    public abstract void age();
    public abstract void brither();
    public abstract void X();
    public abstract void XY();
}
package com.JavaBasicsDemo6.Abstract1;
//单继承
public  class B extends A{//B类是抽象类的子类,是一个普通类
    @Override
    public void print() {//强制要求覆写
        System.out.println("Hello World !");
    }
    @Override
    public void sleep() {
        System.out.println("我再睡觉");
    }
    @Override
    public void height() {
        System.out.println("小工的身高178cm");
    }
    @Override
    public void weight() {
        System.out.println("小工的体重89kg");
    }
    @Override
    public void name() {
        System.out.println("小工");
    }
    @Override
    public void age() {
        System.out.println("20岁");
    }
    @Override
    public void brither() {
        System.out.println("2000/10/30");
    }
    @Override
    public void X() {
    }
    @Override
    public void XY() {
        System.out.println("XYXYXY");
    }
}
package com.JavaBasicsDemo6.Abstract1;
public class TestDemo {
    public static void main(String[] args) {
        A a = new B();//向上转型
        a.fun();
        a.print();//被子类所覆写的过的方法
        a.sleep();
        a.brither();
        a.height();
        a.age();
        a.name();
        a.weight();
        a.XY();
    }
}

案例三:

(1)抽象类中有构造方法么?

由于抽象类里会存在一些属性,那么抽象类中一定存在构造方法,其存在目的是为了属性的初始化。

并且子类对象实例化的时候,依然满足先执行父类构造,再执行子类构造的顺序。

package com.JavaBasicsDemo6.Abstract2;
abstract class A{//定义一个抽象类
    public A(){
        System.out.println("*****A类构造方法*****");
    }
    public abstract void print();//抽象方法,没有方法体,有abstract关键字做修饰
}
package com.JavaBasicsDemo6.Abstract2;
/**
 * (1)抽象类中有构造方法么?
 * 由于抽象类里会存在一些属性,那么抽象类中一定存在构造方法,其存在目的是为了属性的初始化。
 * 并且子类对象实例化的时候,依然满足先执行父类构造,再执行子类构造的顺序。
 */
 abstract class B extends A{//B类是抽象类的子类,是一个普通类
    public B(){
        System.out.println("*****B类构造方法*****");
    }
    @Override
    public void print() {//强制要求覆写
        System.out.println("Hello World !");
    }
}
package com.JavaBasicsDemo6.Abstract2;
public class C extends  B {
    @Override
    public void print() {
        System.out.println("我是c方法");
    }
    public    C(){
        System.out.println("我是c构造的方法");
    }
}
package com.JavaBasicsDemo6.Abstract2;
public class TestDemo {
    public static void main(String[] args) {
        A a = new C();//向上转型
        a.print();
    }
}

案例四:

(2)抽象类可以用final声明么?

不能,因为抽象类必须有子类,而final定义的类不能有子类

(3)抽象类能否使用static声明?

先看一个关于外部抽象类的范例:

package com.JavaBasicsDemo6.Abstract3;
  static  abstract class A{//定义一个抽象类
    public abstract void print();
}
package com.JavaBasicsDemo6.Abstract3;
class B extends A{
    public void print(){
        System.out.println("**********");
    }
}
package com.JavaBasicsDemo6.Abstract3;
/**
 * (2)抽象类可以用final声明么?
 * 不能,因为抽象类必须有子类,而final定义的类不能有子类;
 *
 * (3)抽象类能否使用static声明?
 * 先看一个关于外部抽象类的范例:
 */
public class TestDemo {
    public static void main(String[] args) {
        A a = new B();//向上转型
        a.print();
    }
}

案例五:

由此可见,外部抽象类不允许使用static声明,而内部的抽象类运行使用static声明。

使用static声明的内部抽象类相当于一个外部抽象类,继承的时候使用“外部类.内部类”的形式表示类名称。

package com.JavaBasicsDemo6.Abstract4;
abstract class A{//定义一个抽象类
    static abstract class B{//static定义的内部类属于外部类
        public abstract void print();
    }
}
class C extends A.B{
    public void print(){
        System.out.println("**********");
    }
}
class TestDemo {
    public static void main(String[] args) {
        A.B ab = new C();//向上转型
        ab.print();
    }
}
/**
 * 由此可见,外部抽象类不允许使用static声明,而内部的抽象类运行使用static声明。
 * 使用static声明的内部抽象类相当于一个外部抽象类,继承的时候使用“外部类.内部类”的形式表示类名称。
 */

案例六:

可以直接调用抽象类中用static声明的方法么?

任何时候,如果要执行类中的static方法的时候,都可以在没有对象的情况下直接调用,对于抽象类也一样。

范例如下:

package com.JavaBasicsDemo6.Abstract5;
/**
 * 可以直接调用抽象类中用static声明的方法么?
 * 任何时候,如果要执行类中的static方法的时候,都可以在没有对象的情况下直接调用,对于抽象类也一样。
 * 范例如下:
 */
abstract class A{//定义一个抽象类
    public static void print(){
        System.out.println("Hello World !");
    }
}
class TestDemo {
    public static void main(String[] args) {
        A.print();
    }
}

案例七:

有时候由于抽象类中只需要一个特定的系统子类操作,所以可以忽略掉外部子类。

这样的设计在系统类库中会比较常见,目的是对用户隐藏不需要知道的子类。

package com.JavaBasicsDemo6.Abstract6;
/**
 * 有时候由于抽象类中只需要一个特定的系统子类操作,所以可以忽略掉外部子类。
 * 这样的设计在系统类库中会比较常见,目的是对用户隐藏不需要知道的子类。
 */
abstract class A{//定义一个抽象类
    public abstract void print();
    private static class B extends A{//内部抽象类子类
        public void print(){//覆写抽象类的方法
            System.out.println("Hello World !");
        }
    }
    //这个方法不受实例化对象的控制
    public static A getInstance(){
        return new B();
    }
}
class TestDemo {
    public static void main(String[] args) {
        //此时取得抽象类对象的时候完全不需要知道B类这个子类的存在
        A a = A.getInstance();
        a.print();
    }
}

案例八:综合案例一

package com.JavaBasicsDemo6.Abstract7;
/**
 * 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
 * @author MZFAITHDREAM
 *
 */
public class Circle extends Shape {
    public double r = 10;
    public Circle() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Circle(String shapName, double r) {
        super(shapName);
        this.r = r;
    }
    @Override
    public double getArea() {
        // TODO Auto-generated method stub
        System.out.println("圆的面积为:" + Math.PI * r * r);
        return Math.PI * r * r;
    }
}
package com.JavaBasicsDemo6.Abstract7;
public class Rectangle extends Shape{
    public double width=10;
    public double height=10;
    public Rectangle() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Rectangle(String shapName, double width, double height) {
        super(shapName);
        this.width = width;
        this.height = height;
    }
    @Override
    public double getArea() {
        System.out.println("长方形的面积为:"+width*height);
        return width*height;
    }
}
package com.JavaBasicsDemo6.Abstract7;
/**
 * 求图形面积问题
 * 难以在父类中写出每种图形的求面积的方法
 * 不能在子类中单独实现,否则父类不能使用
 * 解决:
 * 在父类中定义,子类中去实现
 * 1.抽象方法:把没有方法体方法称为抽象方法,抽象方法使用abstract关键字去修饰
 *2.含有抽象方法的类一定是抽象类,这个类要用abstract去修饰
 */
public abstract class Shape {
    public String shapName;
    public Shape() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Shape(String shapName) {
        super();
        this.shapName = shapName;
    }
    public String getShapName() {
        return shapName;
    }
    public void setShapName(String shapName) {
        this.shapName = shapName;
    }
    /*定义求面积的方法*/
    public abstract double getArea();
}
package com.JavaBasicsDemo6.Abstract7;
public abstract class Triangle extends Shape{
    public double border;
    public double height;
    public Triangle(){
        super();
        // TODO Auto-generated constructor stub
    }
    public Triangle(String shapName, double border, double height) {
        super(shapName);
        this.border = border;
        this.height = height;
    }
}
package com.JavaBasicsDemo6.Abstract7;
public class ShapeTest {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Shape s = new Circle();
        s.getArea();
        s.getShapName();
        Shape r = new Rectangle();
        r.getArea();
        r.getShapName();
    }
}
相关文章
|
7月前
|
Java 编译器
重温经典《Thinking in java》第四版之第八章 多态(四十三)
重温经典《Thinking in java》第四版之第八章 多态(四十三)
54 1
|
6月前
|
Java
JavaSE 面向对象程序设计进阶 继承和方法重写 2024理论与内存详解
JavaSE 面向对象程序设计进阶 继承和方法重写 2024理论与内存详解
36 3
|
6月前
|
Java
深入 Java 面向对象:类的定义,竟然藏着这么多门道!
【6月更文挑战第15天】Java中的类定义是OOP的基础,它封装属性(如Student的name和age)和行为(如study())。简单的类仅触及表面,而复杂的类可模拟真实世界对象的多样性和交互。类还可通过继承扩展,如Student从Person派生,增加特有属性和行为。接口和抽象类等概念进一步增强了灵活性和可扩展性。类定义的深度和广度是构建高效、可维护代码的关键。
38 0
|
7月前
|
Java
【JAVA基础篇教学】第五篇:Java面向对象编程:类、对象、继承、多态
【JAVA基础篇教学】第五篇:Java面向对象编程:类、对象、继承、多态
|
7月前
|
Java 编译器
重温经典《Thinking in java》第四版之第八章 多态(四十四)
重温经典《Thinking in java》第四版之第八章 多态(四十四)
65 4
|
7月前
|
安全 Java 程序员
重温经典《Thinking in java》第四版之第八章 多态(四十五)
重温经典《Thinking in java》第四版之第八章 多态(四十五)
55 1
|
7月前
|
设计模式 算法 Java
重温经典《Thinking in java》第四版之第九章 接口(四十七)
重温经典《Thinking in java》第四版之第九章 接口(四十七)
53 0
|
7月前
|
Java 编译器 C++
重温经典《Thinking in java》第四版之第九章 接口(四十六)
重温经典《Thinking in java》第四版之第九章 接口(四十六)
43 0
|
7月前
|
Java
【Java 多态】面向对象编程の重要概念,多态是什么,附带小案例
【Java 多态】面向对象编程の重要概念,多态是什么,附带小案例
|
存储 Java API
重温经典《Thinking in java》第四版之第二章 一切都是对象(十二)
重温经典《Thinking in java》第四版之第二章 一切都是对象(十二)
51 1