抽象类
abstract 修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类
抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。通过多态来实例对象
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的,
子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
标签:子类,实例,Animal,抽象类,方法,public From: https://www.cnblogs.com/panghuhu-space/p/18669545在面向对象编程中,抽象类是一个不能直接实例化的类,它通常作为其他类的基类,提供通用的接口和部分实现。抽象类的主要目的是为继承它的子类提供一个模板,确保所有子类都实现特定的功能。
主要特点:
- 不能实例化:抽象类不能被直接实例化。你不能创建抽象类的对象,必须通过继承它的子类来实例化。
- 可以包含抽象方法:抽象类可以包含抽象方法(方法声明没有实现),这些方法需要在子类中实现。抽象方法在抽象类中只定义方法签名(包括方法名、参数列表和返回类型),而没有方法体。
- 可以有已实现的方法:除了抽象方法,抽象类还可以包含已实现的方法,这些方法可以被子类继承和重用,或者被子类覆盖(重写)。
- 可以有成员变量:抽象类可以包含成员变量,允许它在多个子类中共享一些数据。
- 可以继承其他类:抽象类可以继承其他类,并且可以实现接口。
抽象类的定义与使用
假设我们有一个动物类
Animal
,我们希望定义一个通用的行为,但不希望直接实例化Animal
类,而是让它的子类具体实现某些特性。package com.oop.demo09; public class Test { public static void main(String[] args) { //new Animal(); //抽象类的实例不是直接new 而是通过多态 父类(抽象类)的引用指向子类的实例 Animal d1 = new Dog();//通过子类将父类(抽象类中的抽象方法)实现且必须全部实现 否则就将子类也声明成抽象类 System.out.println(d1.num); System.out.println(d1.num_float); d1.breath();//父类的引用 直接调用自己的方法(子类没有重写) d1.sound();//子类实例 用重写过的抽象类中抽象方法 Animal c1 = new Cat(); System.out.println(c1.num); System.out.println(c1.num_float); c1.breath();//父类的引用 直接调用自己的方法(子类没有重写) c1.sound();//子类实例 用重写过的抽象类中抽象方法 } } abstract class Animal { public static int num = 123; public float num_float=123.456f; //抽象类中可以定义属性 public void breath(){ //抽象类可以定义普通方法 System.out.println("他在呼吸!"); } public abstract void sound(); //只有方法的声明,没有方法体 //new Animal();//抽象类不能直接实例化,得借助子类进行实例化(多态) //new Dog();//也不能在抽象类里面实例对象 } class Dog extends Animal{ public void sound(){ System.out.println("Bark!");//在子类中将抽象方法具体实现 } } class Cat extends Animal{ public void sound(){ System.out.println("Miao Miao!"); } }
抽象类中可以有:
1. 定义属性
抽象类可以定义属性(成员变量),这些属性可以是静态的(
static
)或实例的。它们可以被继承到子类中。public static int num = 123; // 静态属性 public float num_float = 123.456f; // 实例属性
num
是一个静态属性,可以直接通过Animal
类名访问,并且是所有Animal
类型(包括继承类)共享的。num_float
是一个实例属性,每个Animal
的实例都有自己的副本,子类实例也可以访问该属性。2. 定义普通方法
抽象类可以定义普通(已实现)的方法,子类可以继承并直接使用这些方法,也可以选择覆盖(重写)。
public void breath() { System.out.println("他在呼吸!"); }
breath
是一个普通方法,定义在抽象类Animal
中。它不需要在子类中重写,子类可以直接继承并调用它。3. 定义抽象方法
抽象类中可以定义抽象方法,这些方法没有方法体,必须由子类实现。
public abstract void sound(); // 抽象方法,要求子类必须实现
sound
是一个抽象方法,在Animal
类中没有实现,子类Dog
和Cat
必须实现这个方法。4. 构造方法
抽象类可以有构造方法,但它不能直接实例化。在构造方法中,你可以初始化一些共享的成员或执行其他必要的初始化操作。
abstract class Animal { public Animal() { System.out.println("动物类构造方法"); } // 其他代码 }
Animal
类可以包含构造方法,尽管我们不能直接实例化抽象类,但可以在子类实例化时调用父类的构造方法。5. 静态方法
抽象类也可以有静态方法(
static
),这些方法只能通过类名访问,而不依赖于实例。abstract class Animal { public static void staticMethod() { System.out.println("这是抽象类的静态方法"); } }
- 你可以通过
Animal.staticMethod()
来调用静态方法,而不需要创建实例。6. 接口实现
抽象类可以实现接口。这样,抽象类就可以强制要求所有子类实现接口中的方法,同时又可以提供一些默认的实现。
java复制代码interface Eater { void eat(); } abstract class Animal implements Eater { // 可以不实现接口方法,留给子类去实现 public abstract void sound(); }
总结:在您的代码中,抽象类的以下特性已经体现出来:
- 可以定义成员变量(静态和实例变量)。
- 可以定义普通方法(有方法体的方法)静态方法和非静态方法。
- 可以定义抽象方法(没有方法体的方法,要求子类实现)。
- 可以包含构造方法。
- 子类必须实现抽象类中的所有抽象方法,除非子类本身也是抽象类。
但是,抽象类可以有更多的功能,如:
- 静态方法。
- 可以实现接口。
- 可以包含常量(
public static final
)等。抽象类中的属性只能是常量吗?
不,抽象类中的属性不仅仅可以是常量,它也可以是普通的实例变量(非常量)。抽象类中的属性可以是:
- 实例变量(非常量)
- 静态变量(常量或非常量)
- 常量(
public static final
)1. 实例变量(非常量)
抽象类可以定义实例变量(成员变量),这些变量属于类的实例。每个继承该抽象类的子类对象都有自己独立的副本。子类可以直接访问这些变量,或者通过重写的方法来访问和修改它们。
abstract class Animal { public float num_float = 123.456f; // 实例变量 }
num_float
是实例变量,每个实例(包括子类的实例)都有这个变量的副本。子类可以直接访问它。2. 静态变量(常量或非常量)
抽象类也可以包含静态变量,这些变量属于类本身而不是类的实例。所有通过该类或子类访问这个变量时,都访问的是相同的内存位置。
abstract class Animal { public static int num = 123; // 静态变量 }
num
是静态变量,所有Animal
类及其子类共享这个变量。你可以通过Animal.num
来访问它。3. 常量(
public static final
)常量是指一旦被赋值就不能改变的变量。常量通常是静态的,意味着它们是属于类的,而不是某个实例的。常量在抽象类中使用时一般都加上
public static final
修饰符。abstract class Animal { public static final String TYPE = "动物"; // 常量 }
TYPE
是一个常量,public static final
表示它是类级别的,且值不可更改。它被所有继承Animal
类的子类共享。package com.oop.demo09; public class Test { public static void main(String[] args) { //new Animal(); //抽象类的实例不是直接new 而是通过多态 父类(抽象类)的引用指向子类的实例 Animal.eat();//通过类名直接引用抽象类中的静态方法 Animal d1 = new Dog();//通过子类将父类(抽象类中的抽象方法)实现且必须全部实现 否则就将子类也声明成抽象类 System.out.println(d1.num); System.out.println(d1.num_float); d1.breath();//父类的引用 直接调用自己的方法(子类没有重写) d1.sound();//子类实例 用重写过的抽象类中抽象方法 Animal c1 = new Cat(); System.out.println(c1.num); System.out.println(c1.num_float); c1.breath();//父类的引用 直接调用自己的方法(子类没有重写) c1.sound();//子类实例 用重写过的抽象类中抽象方法 } } abstract class Animal { //抽象类中可以定义属性 静态的 非静态的都可以 public static int num = 123; public float num_float=123.456f; //抽象类可以定义构造器 public Animal(){ } //抽象类可以定义静态方法 public static void eat(){ System.out.println("他在吃东西!"); } public void breath(){ //抽象类可以定义实例方法 System.out.println("他在呼吸!"); } public abstract void sound(); //只有方法的声明,没有方法体 //new Animal();//抽象类不能直接实例化,得借助子类进行实例化(多态) //new Dog();//也不能在抽象类里面实例对象 } class Dog extends Animal{ public void sound(){ System.out.println("Bark!");//在子类中将抽象方法具体实现 } } class Cat extends Animal{ public void sound(){ System.out.println("Miao Miao!"); } }
输出结果:
他在吃东西! 123 123.456 他在呼吸! Bark! 123 123.456 他在呼吸! Miao Miao!