Tại sao phải dùng abstract class

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ụ:

Nội dung chính

Show

  • Sự khác nhau giữa Interface và Abstract
  • Abstract là gì?
  • Interface là gì?
  • Khi nào nên dùng?
  • Video liên quan

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”);
}
}

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

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 abstractmakeSound() 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.”);
}
}

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();

}
}

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.

Bài trước và bài sau trong môn học

Trong java, chúng ta có class abstract và một Interface, ai cũng biết một class có thể impements nhiều Interface và chỉ kế thừa được một class abstract. Nhưng bạn thực sự đã biết khi nào thì ta dùng Interface, khi nào dùng Abstract. Chưa kể bắt đầu từ Java 8 có sự thay đổi về Interface càng làm khó phân biệt giữa hai loại này.

Trong bài viết này chúng tôi sẽ đi so sánh một số tính chất của 2 loại này, sau đó là đưa ra ví dụ đơn giải để các bạn hình dung rõ nhất. Cuối cùng là hiểu khi nào thì dùng chúng.

Sự khác nhau giữa Interface và Abstract

  1. Methods: Class abstract có các phương thức abstract và non-abstract. Trong khi Interface chỉ có phương thức abstract, từ Java 8, thì Interface có thêm 2 loại phương thức là default và static.
  2. Variables: Class abstract có thể có các biến final, non-final, static và non-static. Trong khi Interface chỉ có các biến static và final.
  3. Implementation: Class abstract có thể implement các Interface. Trong khi Interface thì không thể implement class abstract.
  4. Inheritance: Class abstract có thể kế thừa được một class khác. Trong khi Interface có thể kế thừa được nhiều Interface khác.
  5. Accessibility: các thành viên trong Interface kiếu mặc định là public. Trong khi class abstract thì lại có thể là private, protected,..

Abstract là gì?

Abstract(trừu tượng) nghĩa là một cái gì đó không hoàn toàn cụ thể, nó chỉ là một ý tưởng hoặc ý chính của một cái gì đó mà không có bản triển khai cụ thể. Vì vậy Class abstract chỉ là một cấu trúc hoặc hướng dẫn được tạo cho các class cụ thể khác.

Chúng ta có thể nói rằng một class abstract là linh hồn của một class cụ thể, và rõ ràng một cơ thể (class) không thể có hai linh hồn. Đây cũng là lý do Java không hỗ trợ nhiều kế thừa cho các class abstract.

Hãy nhìn vào class abstract sau:
Xe.class

public abstract class Xe {
private String dongCo;
abstract void khoiDongDongCo();
abstract void dungDongco();
}

Chúng tôi tạo một class abstract Xecó thuộc tính là động cơ, và các phương thức khởi động/ dừng động cơ. Xe là một cái gì đó không cụ thể, nó có thể là ô tô, xe máy, … và rõ ràng không có Xe nào mà không tồn tại động cơ và cơ chế khởi động/dừng động cơ cả.

Oto.class

public class Oto extends Xe {
@Override
void khoiDongDongCo() {
System.out.println(“Khởi động động cơ của ôtô”);
}
@Override
void dungDongco() {
System.out.println(“Dừng động cơ của ôtô”);
}
}

Interface là gì?

Interface (Giao diện) là một hình thức, giống như một hợp đồng, nó không thể tự làm bất cứ điều gì. Nhưng khi có một class ký kết hợp đồng (implement Interface) này, thì class đó phải tuân theo hợp đồng này.

Trong Interface, chúng tôi định nghĩa các hành vi của một class sẽ thực hiện. Một class có thể có một số cách hành vi khác nhau, cũng giống như nó có thể ký kết được với nhiều hợp đồng khác nhau. Đó cũng là lý do tại sao Java cho phép implement nhiều Interface.

Tiếp nối ví dụ trên, Xe có thể di chuyển, vì vậy chúng tôi tạo một Interface Hành động di chuyển và class Oto implement nó.

HanhDongDiChuyen.class

public interface HanhDongDiChuyen {
void diChuyen();
}

Đây là những hành vi của Oto, chứ không thuộc tính sẵn có của nó: Ôtô là xe hơi, ngay cả khi nó không thể di chuyển được!

Oto.class

public class Oto extends Xe implements HanhDongDiChuyen{
@Override
void khoiDongDongCo() {
System.out.println(“Khởi động động cơ của ôtô”);
}
@Override
void dungDongco() {
System.out.println(“Dừng động cơ của ôtô”);
}
@Override
public void diChuyen() {
System.out.println(“Ôtô đang di chuyển”);
}
}

Khi nào nên dùng?

  1. Class abstract đại diện cho mối quan hệ “IS – A” (Ôtô là Xe)
  2. Interface đại diện cho mối quan hệ “like – A” (Ô tô có thể chuyển động).
  3. Tạo một class abstract khi bạn đang cung cấp các hướng dẫn cho một class cụ thể.
  4. Tạo Interface khi chúng ta cung cấp các hành vi bổ sung cho class cụ thể và những hành vì này không bắt buộc đối với clas đó.
    ### Kết luận
    Mục đích của bài viết này là để giúp bạn hiểu và nắm vững class abstract, Interface và kịch bản sử dụng. Thông qua nổ lực toàn bộ bài viết của chúng tôi, chúng tôi tin chắc rằng bạn đã hiểu được điều gì đó :D. Cuối cùng, cảm ơn bạn đã đọc bài viết.

Cùng một tác giả

Tại sao phải dùng abstract class

18 0

Vì sao bạn nên học Java? Trước khi nói Spring Boot, chúng ta nói về nền tảng của nó, chính là Java. Java ra đời năm 1991, tới nay thì đã gần 30 n…

Tại sao phải dùng abstract class

9 0

Vì sao bạn nên học Java? Trước khi nói Spring Boot, chúng ta nói về nền tảng của nó, chính là Java. Java ra đời năm 1991, tới nay thì đã gần 30 n…

Tại sao phải dùng abstract class

9 0

Xin chào tất cả các bạn, trước khi đi vào chi tiết bài hôm nay, các bạn cần đọc cho mình các khái niệm sau: 1. Khái niệm tightcoupling (liên k…

Bài viết liên quan

Tại sao phải dùng abstract class

4 0

I used Spring boot, Hibernate few times back then at University, I’v started using it again recently. In this (Link), I want to check how Spring J…