1. Lớp trừu tượng (abstract class) là gì?
Trong Java, lớp trừu tượng (abstract class) không thể tạo ra các đối tượng. Chúng ta có thể sử dụng từ khóa abstract để khai báo một lớp trừu tượng. Ví dụ:
//tạo một lớp trừu tượng
abstract class Language {
//thân lớp trừu tượng
}
...
//tạo một đối tượng Language sẽ gây lỗi
Language obj = new Language();
Có thể khai báo các thuộc tính trong lớp trừu tượng. Lớp trừu tượng có cả phương thức bình thường (regular method) và phương thức trừu tượng (abstract method).
abstract class Language {
int bienA;
// abstract method
abstract void method1();
// regular method
void method2() {
System.out.println("This is regular method");
}
}
2. Phương thức trừu tượng (abstract method)
Phương thức abstract không có thân phương thức. Chúng ta sử dụng từ khóa abstract để khai báo phương thức abstract và kết thúc bởi dấu chấm phẩy “;”. Ví dụ:
abstract void display();
Nếu một lớp bao gồm abstract method nhưng không được khai báo là lớp abstract thì sẽ gây ra lỗi. Ví dụ:
//lỗi, lớp Language phải được khai báo abstract
class Language {
// abstract method
abstract void method1();
}
Nhưng một lớp được khai báo abstract thì không nhất thiết phải có phương thức abstract trong nó. Và lớp abstract không thể tạo ra các đối tượng nhưng có thể được sử dụng để các lớp khác kế thừa.
abstract class Language {
public void display() {
System.out.println("This is Java Programming");
}
}
class Main extends Language {
public static void main(String[] args) {
Main obj = new Main();
//gọi phương thức của lớp abstract bằng đối tượng của lớp con Main
obj.display();
}
}
Kết quả
This is Java Programming
3. Định nghĩa phương thức abstract trong lớp con
Nếu lớp abstract có bất kỳ phương thức abstract nào, thì tất cả những lớp con kế thừa lớp abstract này đều phải định nghĩa lại những phương thức abstract của lớp đó. Ví dụ:
abstract class Animal {
//hàm abstract
abstract void makeSound();
public void eat() {
System.out.println("I can eat.");
}
}
class Dog extends Animal {
//định nghĩa hàm abstract của lớp cha ở lớp con
@Override
public void makeSound() {
System.out.println("Bark bark");
}
}
class Main {
public static void main(String[] args) {
//tạo một đối tượng của lớp Dog
Dog d1 = new Dog();
d1.makeSound();
d1.eat();
}
}
Kết quả
Bark bark
I can eat.
Trong ví dụ trên, lớp abstract Animal gồm phương thức abstract là makeSound()
và phương thức bình thường là eat()
.
Lớp Dog kế thừa lớp Animal thì lớp Dog bắt buộc phải định nghĩa lại hàm makeSound()
của lớp Animal.
Lưu ý: Nếu lớp Dog cũng được khai báo là lớp abstract thì lớp Dog có thể định nghĩa lại hoặc không cần định nghĩa lại hàm abstract của lớp Animal. Lúc này, lớp abstract Dog kế thừa lớp abstract Animal.
abstract class Animal {
//hàm abstract
abstract void makeSound();
public void eat() {
System.out.println("I can eat.");
}
}
//lớp abstract Dog kế thừa lớp abstract Animal
abstract class Dog extends Animal {
public void sleep() {
System.out.println("I can sleep.");
}
}
4. Truy cập hàm khởi tạo của lớp abstract
Một lớp abstract có thể có hàm khởi tạo như một lớp bình thường. Và chúng ta có thể gọi hàm khởi tạo của lớp abstract với từ khóa super.
abstract class Animal {
Animal() {
….
}
}
class Dog extends Animal {
Dog() {
super();
...
}
}
5. Một số lưu ý khi sử dụng lớp abstract
Tại sao cần sử dụng lớp và phương thức abstract
Mục đích chính khi sử dụng lớp và phương thức abstract là để đạt được tính trừu tượng trong Java. Tính trừu tượng giúp ẩn đi những thông tin phức tạp, không cần thiết của đối tượng.
Ví dụ: Một chiếc xe máy có thể khai báo là một lớp trừu tượng với phương thức trừu tượng là brake()
– bóp thắng xe. Mỗi loại xe máy như xe máy thể thao, xe máy leo núi,… sẽ có cách bóp thắng xe khác nhau. Việc bóp thắng xe máy thực hiện như thế nào sẽ được ẩn với chúng ta. Chúng ta chỉ cần biết bóp thắng xe máy là xe máy sẽ dừng, không cần quan tâm đến cách bóp thắng của từng loại xe máy khác nhau. Nói cách khác, tất cả các loại xe máy đều chỉ có 1 hành động là brake()
thì xe máy sẽ dừng. Điều này đơn giản, dễ hiểu và nó là đặc tính chung của tất cả loại xe máy.
abstract class MotorBike {
abstract void brake();
}
class SportsBike extends MotorBike {
// implementation of abstract method
public void brake() {
System.out.println("SportsBike Brake");
}
}
class MountainBike extends MotorBike {
// implementation of abstract method
public void brake() {
System.out.println("MountainBike Brake");
}
}
class Main {
public static void main(String[] args) {
MountainBike m1 = new MountainBike();
m1.brake();
SportsBike s1 = new SportsBike();
s1.brake();
}
}
Kết quả
MountainBike Brake
SportsBike Brake
Một số lưu ý cần nhớ khi sử dụng lớp abstract
Chúng ta sử dụng từ khóa abstract để tạo ra những lớp và phương thức trừu tượng.
Một phương thức trừu tượng chỉ được khai báo mà không có định nghĩa không thân hàm. Một lớp bao gồm phương thức abstract thì phải được khai báo là lớp abstract.
Chúng ta không thể tạo ra các đối tượng của lớp abstract.
Những lớp con kế thừa lớp abstract thì phải định nghĩa lại các phương thức abstract của lớp đó. Nhưng nếu lớp con cũng là lớp abstract thì không bắt buộc định nghĩa lại các phương thức abstract của lớp cha.
Chúng ta có thể truy cập các thuộc tính và phương thức static của lớp abstract với tên lớp như bình thường. Ví dụ:
abstract class AClass{
static int bienA;
static void ham1(){
System.out.println("bienA = " + bienA);
}
}
class Main {
public static void main(String[] args) {
AClass.bienA = 5;
AClass.ham1();
}
}
Kết quả
bienA = 5
Ở ví dụ trên, truy xuất biến static bienA và phương thức static ham1()
bởi tên lớp abstract AClass.