浅谈Java面向对象之抽象类(abstract)

浅谈Java面向对象之抽象类(abstract),第1张

浅谈Java面向对象之抽象类(abstract)

java语言,声明类时格式为: abstract class Db{} 说明Db类为抽象类。抽象方法是说没有方法的实现(方法体)此方法为抽象方法,只有抽象类和接口中才可以有抽象方法。简而言之,含有抽象方法的类一定是抽象类;关键字是abstract

抽象类本质

1.从类的组成上看其是抽象方法和非抽象方法的集合,还有属性(常量)。
2.从设计的角度来看,实际上抽象类定义了一套规范(抽象方法)。(规范)

使用规则
  1. 抽象类必须被继承,抽象方法必须被重写。
  2. 抽象类中的抽象方法只需声明,无需实现,没有方法体;
  3. 抽象类不能被实例化,抽象类不一定要包含抽象方法,而定义抽象方法的类必须是抽象类。
  4. 抽象类包含的抽象方法必须在其子类中被实现,否则该子类也必须是抽象类。
  5. 抽象类可以有构造方法供子类实例化对象
  6. 抽象类不能直接实例化使用,一般用的是抽象类的子类
    A a = new B();
    A和B之间的关系,继承关系,接口实例关系。

下面逐条解释:

规则一

抽象类必须被继承,抽象方法必须被重写。

规则二

抽象类中的抽象方法只需声明,无需实现,没有方法体。
在Java中抽象类实际上是一种规范,一般在抽象类中声明方法不直接提供方法体(当然也可以提供),而是通过其子类去重写其抽象方法:

package day_12_01.abs;


public abstract class A {
    //报错,不能定义抽象属性
//    abstract int a;

    //可以声明属性
   private int a;
    //可以声明一个普通方法
    public void a(){

    }
    //报错,因为抽象方法不能有方法体,即不能去实现
//    public abstract void aa(){
//
//    }
    //抽象方法正确格式
    public abstract void aa();
    
    //抽象方法不能是私有的private
//    private abstract  void bb();
}
//没有重写父类的抽象方法aa(),报错
//class B extends A{
//
//}

注意

抽象方法不能是私有的private,因为一旦私有,子类就不能重写了,但这违背了抽象方法必须被重写的原则。

规则三

抽象类不能被实例化,抽象类不一定要包含抽象方法,而定义抽象方法的类必须是抽象类。
首先,抽象类不能被实例化,当一个类实例化对象后,这个对象就可以调用类中的属性或者方法了,但在抽象类有抽象方法(没有方法体),无法调用。自相矛盾,所以无法实例化。比如,我想实例化上例中的抽象类A:

class TestA{
    public static void main(String[] args) {
        //报错
//        A a = new A();
    }
}

抽象类不一定有抽象方法,这点显而易见,但是意义不大:

//一个空的抽象类
abstract class AA{
    
}

然后,定义抽象方法的类必须是抽象类,这点也很好理解,一个普通的类是可以被实例化的,如果这个普通类存在抽象方法,那我是不是就可以通过对象去调用呢?当然不能。

package day_12_01.abs;


//报错,因为抽象方法必须声明在抽象类中
//public  class B {
//    public abstract void b();
//}

规则四

抽象类包含的抽象方法必须在其子类中被实现,否则该子类也必须是抽象类。
还拿上述代码做例子,如果我声明了一个类B,继承于A,那B就必须重写A中的抽象方法,否则报错(因为普通类中不能有抽象方法),解决方式一:重写父类抽象方法;解决方式二:将B声明为abstract:

//解决方式一:重写父类抽象方法
class B extends A{
    @Override
    public void aa() {

    }
}
//解决方式二:将B声明为abstract
abstract class Bb extends A{

}
规则五

抽象类可以有构造方法供子类实例化对象。
这点很好理解,因为首先可以确定的是,Java中所有的类都有构造方法,即使你是抽象类,虽然我们没写,但其实系统已经默认给我们提供了一个无参的空构造器,例如下面我显示化的在抽象类中声明一个构造方法:

package day_12_01.abs;


public abstract class Ab {
    public Ab(){
        System.out.println("Abs......");
    }
}
class Abs extends Ab{

}
class Test{
    public static void main(String[] args) {
        Abs abs = new Abs();
    }
}

运行结果:

证明我们在创建子类实例化对象时,父类的构造器也可实现(哪怕父类是抽象类)

规则六

抽象类不能直接实例化使用,一般用的是抽象类的子类。
抽象类不能去实例化对象,那如果我想用其中的一些非抽象方法呢,比如静态方法,比如普通方法呢或者是属性?
我们可以通过继承关系,去创建其子类的对象,形如:

A a = new B(); //其中A是父类,B是子类

package day_12_01.abs;


public abstract class TT {

    String some = "hello";

    public static void talk() {
        System.out.println("talk...");
    }

    public void say() {
        System.out.println("say..." + some);
    }
}

class FF extends TT{

}
class FFTest{
    public static void main(String[] args) {
        TT.talk();
        TT f = new FF();
        f.say();
    }
}

运行结果:

如果子类重写了父类的非抽象方法,那实际调用的就是子类重写后的。通过子类去调用父类的方法,即通过父类去new一个子类的对象,这实际上也是多态性的一种体现。当然了,抽象类中的静态方法是可以直接调用的(除非是私有的),实际上对任何类都一样。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5637466.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存