Abstract class và Interface trong Java
1. Giới thiệu
Trong tài liệu hướng dẫn này tôi sẽ hướng dẫn về Interface và class trừu tượng (Abstract Class). Đồng thời phân tích sự giống và khác nhau giữa chúng.
2. Class trừu tượng (Abstract Class)
Abstract class (Class trừu tượng). Hãy xem ví dụ về một class như thế:
// Đây là một lớp trừu tượng.
// Nó bắt buộc phải khai báo là abstract
// vì trong nó có một phương thức trừu tượng
public abstract class ClassA {
// Đây là một phương thức trừu tượng.
// Nó không có thân (body).
// Access modifier của phương thức này là public.
public abstract void doSomething();
// Access modifier của phương thức này là protected.
protected abstract String doNothing();
// Phương thức này không khai báo access modifier.
// Access modifier của nó là mặc định.
abstract void todo() ;
}
// Đây là một lớp trừu tượng.
// Nó được khai báo là abstract,
// mặc dù nó không có phương thức trừu tượng nào.
public abstract class ClassB {
}
Đặc điểm của một class trừu tượng là:
- Nó được khai báo abstract.
- Nó có thể khai báo 0, 1 hoặc nhiều method trừu tượng bên trong.
- Không thể khởi tạo 1 đối tượng trực tiếp từ một class trừu tượng.
3. Ví dụ với lớp trừu tượng
Hãy xem hình minh họa:
AbstractJob.java
package org.o7planning.tutorial.abs;
// Một lớp trừu tượng (Mô phỏng một công việc)
// Nó khai báo 2 phương thức trừu tượng.
public abstract class AbstractJob {
public AbstractJob() {
}
// Đây là một phương thức trừu tượng.
// Method này trả về tên của công việc.
public abstract String getJobName();
// Đây là một phương thức trừu tượng.
public abstract void doJob();
}
JavaCoding.java
package org.o7planning.tutorial.abs;
// Lớp này thực hiện hết các phương thức trừu tượng của lớp cha.
public class JavaCoding extends AbstractJob {
public JavaCoding() {
}
// Thực hiện phương thức trừu tượng khai báo tại lớp cha.
@Override
public void doJob() {
System.out.println("Coding Java...");
}
// Thực hiện phương thức trừu tượng khai báo tại lớp cha.
// Phương thức này sẽ có thân (body).
// Và trả về tên của công việc.
@Override
public String getJobName() {
return "Coding Java";
}
}
ManualJob.java
package org.o7planning.tutorial.abs;
// ManualJob - (Mô phỏng một công việc phổ thông)
// Lớp cha (AbstractJob) có 2 phương thức trừu tượng.
// Lớp này mới chỉ thực hiện 1 phương thức trừu tượng của lớp cha.
// Vì vậy nó bắt buộc phải khai báo là abstract.
public abstract class ManualJob extends AbstractJob {
public ManualJob() {
}
// Thực hiện phương thức trừu tượng của lớp cha.
@Override
public String getJobName() {
return "Manual Job";
}
}
BuildHouse.java
package org.o7planning.tutorial.abs;
// Class này thừa kế từ class trìu tượng ManualJob
// BuildHouse không được khai báo là trừu tượng.
// Vì vậy nó cần thực hiện tất cả các phương thức trừu tượng còn lại.
public class BuildHouse extends ManualJob {
public BuildHouse() {
}
// Thực hiện phương thức trừu tượng của lớp cha.
@Override
public void doJob() {
System.out.println("Build a House");
}
}
Ví dụ demo
JobDemo.java
package org.o7planning.tutorial.abs;
public class JobDemo {
public static void main(String[] args) {
// Khởi tạo một đối tượng AbstractJob
// từ Constructor của lớp JavaCoding.
AbstractJob job1 = new JavaCoding();
// Gọi phương thức doJob()
job1.doJob();
// Phương thức getJobName là trừu tượng trong lớp AbstractJob.
// Nhưng nó đã được thực hiện tại một lớp con nào đó.
// Vì vậy bạn có thể gọi nó.
String jobName = job1.getJobName();
System.out.println("Job Name 1= " + jobName);
// Khởi tạo một đối tượng AbstractJob
// từ Constructor của lớp BuildHouse.
AbstractJob job2 = new BuildHouse();
job2.doJob();
String jobName2 = job2.getJobName();
System.out.println("Job Name 2= " + jobName2);
}
}
Kết quả chạy ví dụ:
Coding Java...
Job Name 1= Coding Java
Build a House
Job Name 2= Manual Job
4. Tổng quan về Interface
Chúng ta biết rằng một class chỉ có thể mở rộng từ một class cha.
// Lớp B là con của lớp A, hoặc nói cách khác là B mở rộng từ A
// Java chỉ cho phép một lớp mở rộng từ duy nhất một lớp khác.
public class B extends A {
// ....
}
// Trong trường hợp không chỉ rõ lớp B mở rộng từ một lớp cụ thể nào.
// Mặc định, hiểu rằng B mở rộng từ lớp Object.
public class B {
}
// Cách khai báo này, và cách phía trên là tương đương nhau.
public class B extends Object {
}
Nhưng một class có thể mở rộng từ nhiều Interface
// Một lớp chỉ có thể mở rộng từ 1 lớp cha.
// Nhưng có thể thực hiện (mở rộng) từ nhiều Interface.
public class Cat extends Animal implements CanEat, CanDrink {
// ....
}
The characteristics of the interface
- Interface luôn luôn có modifier là: public interface, cho dù bạn có khai báo rõ hay không.
- Nếu có các trường (field) thì chúng đều là: public static final, cho dù bạn có khai báo rõ hay không.
- Các method của nó đều là method trừu tượng, nghĩa là không có thân hàm, và đều có modifier là: public abstract, cho dù bạn có khai báo hay không.
- Interface không có Constructor (cấu tử).
5. Cấu trúc của một Interface
NoAccessModifierInterface.java
package org.o7planning.tutorial.itf;
// Đây là một interface không chỉ định rõ 'access modifier'.
// Access modifier của nó là mặc định.
// Chỉ các lớp cùng package mới có thể thi hành interface này.
interface NoAccessModifierInterface {
}
CanMove.java
package org.o7planning.tutorial.itf;
// Interface này định nghĩa một tiêu chuẩn
// về những thứ có khả năng di chuyển.
public interface CanMove {
// Các phương thức trong Interface đều là trừu tượng và public.
public abstract void run();
// Cho dù bạn không viết rõ 'public abstract' thì java luôn hiểu là vậy.
void back();
// Tốc độ.
public int getVelocity();
}
CanDrink.java
package org.o7planning.tutorial.itf;
// Interface này định nghĩa ra một tiêu chuẩn
// về những thứ có khả năng biết uống.
public interface CanDrink {
// Các trường (field) trong Interface đều là 'public static final'.
// Cho dù bạn có khai báo rõ hay không java luôn hiểu ngầm vậy.
public static final String PEPSI = "PEPSI";
final String NUMBER_ONE = "NUMBER ONE";
String SEVENUP = "SEVEN UP";
public void drink();
}
CanEat.java
package org.o7planning.tutorial.itf;
// Interface này định nghĩa ra một tiêu chuẩn
// về những thứ có khả năng biết ăn.
public interface CanEat {
public void eat();
}
6. Class thực hiện Interface
Animal.java
package org.o7planning.tutorial.cls;
import org.o7planning.tutorial.itf.CanMove;
// Animal (Động vật).
// Lớp này mở rộng từ lớp Object (Mặc dù không ghi rõ).
// Và được khai báo thực hiện hiện (hoặc gọi là thừa kế) interface CanMove.
// Interface CanMove có 3 phương thức trừu tượng.
// Lớp này chỉ thực hiện 1 phương thức.
// Vì vậy nó bắt buộc phải khai báo là abstract.
// Các phương thức trừu tượng còn lại sẽ được các lớp con thực hiện.
public abstract class Animal implements CanMove {
// Thực hiện phương thức run() của interface CanMove.
@Override
public void run() {
System.out.println("Animal run...");
}
}
Cat.java
package org.o7planning.tutorial.cls;
import org.o7planning.tutorial.itf.CanDrink;
import org.o7planning.tutorial.itf.CanEat;
// Lớp Cat mở rộng từ lớp Animal và thi hành 2 interface CanEat, CanDrink.
// Cat là lớp thông thường (Nó không được khai báo là trừu tượng).
// Vì vậy nó phải thực hiện mọi phương thức trừu tượng của các Interface.
public class Cat extends Animal implements CanEat, CanDrink {
private String name;
public Cat(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
// Thực hiện phương thức của interface CanMove.
@Override
public void back() {
System.out.println(name + " cat back ...");
}
// Thực hiện phương thức của interface CanMove.
@Override
public int getVelocity() {
return 110;
}
// Thực hiện phương thức của interface CanEat.
@Override
public void eat() {
System.out.println(name + " cat eat ...");
}
// Thực hiện phương thức của interface CanDrink.
@Override
public void drink() {
System.out.println(name + " cat drink ...");
}
}
Mouse.java
package org.o7planning.tutorial.cls;
import org.o7planning.tutorial.itf.CanDrink;
import org.o7planning.tutorial.itf.CanEat;
public class Mouse extends Animal implements CanEat, CanDrink {
@Override
public void back() {
System.out.println("Mouse back ...");
}
@Override
public int getVelocity() {
return 85;
}
@Override
public void drink() {
System.out.println("Mouse drink ...");
}
@Override
public void eat() {
System.out.println("Mouse eat ...");
}
}
AnimalDemo.java
package org.o7planning.tutorial.cls;
import org.o7planning.tutorial.itf.CanEat;
public class AnimalDemo {
public static void main(String[] args) {
// Thừa kế trường tĩnh từ interface CanDrink.
System.out.println("Drink " + Cat.SEVENUP);
// Khởi tạo một đối tượng CanEat.
// Một đối tượng khai báo là CanEat.
// Nhưng thực tế là Cat.
CanEat canEat1 = new Cat("Tom");
// Một đối tượng khai báo là CanEat.
// Nhưng thực tế là Mouse.
CanEat canEat2 = new Mouse();
// Tính đa hình (Polymorphism) thể hiện rõ tại đây.
// Java luôn biết một đối tượng là kiểu gì
// ==> Tom cat eat ...
canEat1.eat();
// ==> Mouse eat ...
canEat2.eat();
boolean isCat = canEat1 instanceof Cat;
System.out.println("catEat1 is Cat? " + isCat);
// Ép kiểu (Cast).
if (canEat2 instanceof Mouse) {
Mouse mouse = (Mouse) canEat2;
// Gọi phương thức drink (Thừa kế từ CanDrink).
mouse.drink();
}
}
}
Kết quả chạy ví dụ:
Drink SEVEN UP
Tom cat eat ...
Mouse eat ...
catEat1 is Cat? true
Mouse drink ...
Java cơ bản
- Tùy biến trình biên dịch java xử lý Annotation của bạn (Annotation Processing Tool)
- Lập trình Java theo nhóm sử dụng Eclipse và SVN
- Hướng dẫn và ví dụ Java WeakReference
- Hướng dẫn và ví dụ Java PhantomReference
- Hướng dẫn nén và giải nén trong Java
- Cấu hình Eclipse để sử dụng JDK thay vì JRE
- Phương thức String.format() và printf() trong Java
- Cú pháp và các tính năng mới trong Java 5
- Cú pháp và các tính năng mới trong Java 8
- Hướng dẫn sử dụng biểu thức chính quy trong Java
- Hướng dẫn lập trình đa luồng trong Java - Java Multithreading
- Thư viện điều khiển các loại cơ sở dữ liệu khác nhau trong Java
- Hướng dẫn sử dụng Java JDBC kết nối cơ sở dữ liệu
- Lấy các giá trị của các cột tự động tăng khi Insert một bản ghi sử dụng JDBC
- Hướng dẫn và ví dụ Java Stream
- Functional Interface trong Java
- Giới thiệu về Raspberry Pi
- Hướng dẫn và ví dụ Java Predicate
- Abstract class và Interface trong Java
- Access modifier trong Java
- Hướng dẫn và ví dụ Java Enum
- Hướng dẫn và ví dụ Java Annotation
- So sánh và sắp xếp trong Java
- Hướng dẫn và ví dụ Java String, StringBuffer và StringBuilder
- Hướng dẫn xử lý ngoại lệ trong Java - Java Exception Handling
- Hướng dẫn và ví dụ Java Generics
- Thao tác với tập tin và thư mục trong Java
- Hướng dẫn và ví dụ Java BiPredicate
- Hướng dẫn và ví dụ Java Consumer
- Hướng dẫn và ví dụ Java BiConsumer
- Bắt đầu với Java cần những gì?
- Lịch sử của Java và sự khác biệt giữa Oracle JDK và OpenJDK
- Cài đặt Java trên Windows
- Cài đặt Java trên Ubuntu
- Cài đặt OpenJDK trên Ubuntu
- Cài đặt Eclipse
- Cài đặt Eclipse trên Ubuntu
- Học nhanh Java cho người mới bắt đầu
- Lịch sử của bit và byte trong khoa học máy tính
- Các kiểu dữ liệu trong Java
- Các toán tử Bitwise
- Câu lệnh rẽ nhánh (if else) trong Java
- Câu lệnh rẽ nhánh switch trong Java
- Vòng lặp trong Java
- Mảng (Array) trong Java
- JDK Javadoc định dạng CHM
- Thừa kế và đa hình trong Java
- Hướng dẫn và ví dụ Java Function
- Hướng dẫn và ví dụ Java BiFunction
- Ví dụ về Java encoding và decoding sử dụng Apache Base64
- Hướng dẫn và ví dụ Java Reflection
- Hướng dẫn gọi phương thức từ xa với Java RMI
- Hướng dẫn lập trình Java Socket
- Các nền tảng nào bạn nên chọn để lập trình ứng dụng Java Desktop?
- Hướng dẫn và ví dụ Java Commons IO
- Hướng dẫn và ví dụ Java Commons Email
- Hướng dẫn và ví dụ Java Commons Logging
- Tìm hiểu về Java System.identityHashCode, Object.hashCode và Object.equals
- Hướng dẫn và ví dụ Java SoftReference
- Hướng dẫn và ví dụ Java Supplier
- Lập trình Java hướng khía cạnh với AspectJ (AOP)
Show More
- Hướng dẫn lập trình Java Servlet/JSP
- Các hướng dẫn Java Collections Framework
- Java API cho HTML & XML
- Các hướng dẫn Java IO
- Các hướng dẫn Java Date Time
- Các hướng dẫn Spring Boot
- Các hướng dẫn Maven
- Các hướng dẫn Gradle
- Các hướng dẫn Java Web Services
- Các hướng dẫn lập trình Java SWT
- Các hướng dẫn lập trình JavaFX
- Các hướng dẫn Java Oracle ADF
- Các hướng dẫn Struts2 Framework
- Các hướng dẫn Spring Cloud