Phương Thức Trừu Tượng Là Gì - Mới Cập Nhập - Update Thôi

1. Class trừu tượng(Abstract) trong Java

Một class trừu tượng trong Java không thể được khởi tạo (chúng ta không thể tạo ra các đối tượng cho một class trừu tượng). Trong Java, chúng ta chỉ sử dụng từ khóa abstract để khai báo một class trừu tượng.

Nội dung chính Show
  • 1. Class trừu tượng(Abstract) trong Java
  • Java 8 – Lớp và phương thức trừu tượng
  • Mục lục
  • Định nghĩa các loại trừu tượngSửa đổi
  • Ví dụ (Java)Sửa đổi
  • Tính Trừu Tượng (Abstraction) Là Gì?
  • Khai Báo Lớp Trừu Tượng Như Thế Nào?
  • Tại Sao Phải Trừu Tượng?
  • Tính trừu tượng (Abstraction) trong Java
  • Lớp abstract trong Java
  • Phương thức trừu tượng trong Java
  • Ví dụ về lớp trừu tượng và phương thức trừu tượng trong Java
  • Kế thừa lớp Abstract trong Java
  • Ví dụ khác về Kế thừa lớp Abstract trong Java
  • Abtraction (Trừu tượng) là gì trong Lập trình hướng đối tượng (OOP)
abstract class Animal { //attributes and methods }

Nếu cố gắng tạo ra các đối tượng của một class trừu tượng, chúng ta sẽ bị lỗi biên dịch. Lấy ví dụ,

Animal a1 = new Animal()

Nó sẽ bị lỗi biên dịch

Animal is abstract; cannot be instantiated

Mặc dù các class trừu tượng không thể được khởi tạo, chúng ta vẫn có thể tạo ra các subbclass từ nó. Chúng ta có thể tạo các đối tượng của subclass để truy cập các thành viên của class trừu tượng.

Trước khi chúng ta tìm hiểu chi tiết về nó, chúng ta cần hiểu các phương thức trừu tượng.

Java 8 – Lớp và phương thức trừu tượng

  • Phở Code
  • August 11, 2017
  • Không có bình luận

Lớp trừu tượng là lớp được khai báo với từ khóa abstractvà có thể có hoặc không có các phương thức trừu tượng. Lớp trừu tượng không được dùng để tạo ra các đối tượng mà chỉ có thể được kế thừa. Ví dụ:

public abstract class Number() { }

Phương thức trừu tượng là các phương thức chỉ có phần tên chứ không có phần thân, phía sau tên phương thức là dấu chấm phẩy, ví dụ:

abstract double add(double a, double b);

Nếu một lớp có chứa bất kì một phương thức trừu tượng nào thì lớp đó phải là lớp trừu tượng.

public abstract class Number { abstract double add(double a, double b); }

Khi một lớp trừu tượng được kế thừa thì các lớp con luôn luôn phải code lại tất cả các phương thức trừu tượng của lớp cha, nếu không thì lớp con cũng phải khai báo là trừu tượng – abstract.

Lưu ý là tính năng này cũng khá giống vớiinterface, bởi vì trong interface thì một phương thức cũng không có phần thân, và các lớp implement lại interface này cũng phải code lại các phương thức đó.

Mục lục

  • 1 Định nghĩa các loại trừu tượng
    • 1.1 Ví dụ (Java)
  • 2 Cách dùng kiểu trừu tượng
  • 3 Xem thêm
  • 4 Tham khảo
  • 5 Đọc thêm
  • 6 Liên kết ngoài

Định nghĩa các loại trừu tượngSửa đổi

Lớp trừu tượng có thể được tạo ra, định nghĩa, hay mô phỏng, theo nhiều cách:

  • Bằng cách sử dụng từ khóa abstract trong định nghĩa lớp, như trong Java, D hay C#.
  • Bằng cách thêm vào, trong định nghĩa lớp, một hay nhiều phương thức trừu tượng (gọi là các hàm ảo thuần túy trong C++), mà lớp dược khai báo để chấp nhận như là một phần giao thức của nó, nhưng không có hiện thực nào được cung cấp.
  • Bằng cách kế thừa từ một kiểu trừu tượng, nhưng không ghi đè tất cả các tính năng cần thiết để hoàn thành định nghĩa lớp.
  • Một số ngôn ngữ kiểu động như Smalltalk, bất kì lớp này gửi một phương thức cụ thể tới this, nhưng không hiện thực phương thức đó, thì có thể được xem là trừu tượng. (Tuy nhiên, trong nhiều ngôn ngữ, Objective-C, lỗi không được phát hiện đến khi lớp được sử dụng, và thông báo trả về kết quả trong lỗi ngoại lệ như "Does not recognize selector: xxx" as - [NSObject doesNotRecognizeSelector:(SEL)selector] được gọi khi phát hiện phương thức chưa được hiện thực).

Ví dụ (Java)Sửa đổi

//By default, all methods in all classes are concrete, unless the abstract keyword is used. abstract class Demo { // An abstract class may include abstract methods, which have no implementation. abstract public int sum(int x, int y); // An abstract class may also include concrete methods. public int product(int x, int y) { return x*y; } } //By default, all methods in all interfaces are abstract, unless the default keyword is used. interface DemoInterface { [abstract] int getLength(); //Abstract can be used here, though is completely useless //The default keyword can be used in this context to specify a concrete method in an interface default int product(int x, int y) { return x * y; } }

Tính Trừu Tượng (Abstraction) Là Gì?

Trừu tượng trong thực tế còn có thể hiểu là cái gì đó không có thực. Vậy tính Trừu tượng trong OOP ý muốn nói đến một lớp nào đó mang một đặc tính trừu tượng, không có thực. Và như vậy bạn có thể hiểu là lớp Trừu tượng sẽ là lớp không tồn tại đúng không nào?

Thực ra thì lớp Trừu tượng vẫn có tồn tại, vẫn là một lớp thôi. Nhưng nó trừu tượng ở chỗ, nó không thể được dùng để tạo ra các đối tượng như những lớp bình thường khác. Lớp Trừu tượng khi này chỉ là cái “xác không hồn”, hay bạn có thể hiểu nó chỉ là một cái sườn, để mà bạn có thể tạo ra các lớp con của nó dựa vào sự ràng buộc từ cái sườn này.

Nghe đến đây đủ thấy trừu tượng rồi ha. Chúng ta cùng xem khai báo một lớp là Trừu tượng là như thế nào, và các đặc điểm của một lớp Trừu tượng sẽ ra sao với mục kế tiếp.

Khai Báo Lớp Trừu Tượng Như Thế Nào?

Sau đây là cú pháp để bạn có thể khai báo một lớp Trừu tượng.

abstract class tên_lớp { các_thuộc_tính; các_phương_thức; }

Bạn có thể thấy, để khai báo một lớp là Trừu tượng, chỉ cần thêm vào trước từ khóa class một từ khóa abstract mà thôi.

Nhưng như vậy thì mục đích của sự Trừu tượng này là gì, chúng ta cùng đi đến mục sau đây.

Tại Sao Phải Trừu Tượng?

Lý do tiên quyết mà bạn phải biết đến Trừu tượng là vì có trên 90% khả năng bạn đi xin việc, người phỏng vấn sẽ hỏi bạn câu này: “em hãy giúp phân biệt giữa lớp abstract và interface”!!! Mình đùa thôi! Nhưng họ hỏi thật đấy!

Thực ra lý do để khai báo một lớp Trừu tượng là vì trong lớp có ít nhất một phương thức Trừu tượng. Có thể nói ngược lại cho dễ hiểu như sau, nếu mà một lớp có ít nhất một phương thức được định nghĩa là Trừu tượng, thì lớp đó phải khai báo Trừu tượng. Đến đây bạn sẽ có rất nhiều thắc mắc, mình xin giải đáp từ từ.

Phương thức Trừu tượng là gì? Chính là phương thức có định nghĩa từ khóa abstract khi khai báo. Cú pháp khai báo một phương thức Trừu tượng cũng giống như khai báo một lớp Trừu tượng thôi.

[kả_năng_truy_cập] abstract kiểu_trả_về tên_phương_thức ([ các_tham_số_truyền_vào"]);

Phương thức Trừu tượng có tác dụng gì? Phương thức có khai báo abstract sẽ buộc phải không có thân hàm. Như bạn xem cú pháp ở trên, sẽ không có thông tin về khối lệnh của phương thức dạng này. Bạn có thể so sánh với cú pháp của phương thức bình thường ở đây. Bạn chỉ có thể khai báo tên, các tham số truyền vào (nếu có), kiểu trả về, và rồi kết thúc khai báo bằng (;) cho các phương thức Trừu tượng. Có thể thấy rõ sự ràng buộc của tính Trừu tượng bắt đầu ở ngay đây. Sở dĩ các phương thức Trừu tượng không có thân hàm, vì chúng không cần phải làm vậy. Một khi có một lớp nào đó kế thừa từ lớp Trừu tượng này, thì lớp kế thừa đó buộc phải hiện thực (tiếng Anh gọi là implement) nội dung cho tất cả các phương thức Trừu tượng này, bằng cách override lại chúng.

Đến đây bạn có thể thấy lớp Trừu tượng thực sự không quá cao siêu. Nó chỉ là một lớp không có thể hiện (không thể khởi tạo đối tượng từ nó). Nhưng nó lại ràng buộc các lớp con của nó buộc phải hiện thực nội dung cho các phương thức Trừu tượng bên trong nó. Thế thôi.

Bạn có thể bắt gặp tính Trừu tượng này ở đâu đó khi sử dụng các gói thư viện từ hệ thống (thỉnh thoảng có nơi gọi là Java platform) hoặc từ các nhà phân phối khác. Khi bạn kế thừa các lớp của họ, bỗng dưng hệ thống báo lỗi và bắt bạn phải override ngay phương thức nào đó của lớp đó, thì chắc chắn bạn sẽ hiểu ngay lớp đó chính là lớp Trừu tượng. Một lát nữa chúng ta cùng khảo sát xem trong hệ thống thì lớp nào là lớp Trừu tượng nhé, sau khi đi qua bài thực hành bên dưới.

Tính trừu tượng (Abstraction) trong Java

Tính trừu tượng là một tiến trình ẩn các chi tiết trình triển khai và chỉ hiển thị tính năng tới người dùng. Nói cách khác, nó chỉ hiển thị các thứ quan trọng tới người dùng và ẩn các chi tiết nội tại, ví dụ: để gửi tin nhắn, người dùng chỉ cần soạn text và gửi tin. Bạn không biết tiến trình xử lý nội tại về phân phối tin nhắn. Tính trừu tượng giúp bạn trọng tâm hơn vào đối tượng thay vì quan tâm đến cách nó thực hiện.

Lớp abstract trong Java

Một lớp được khai báo là abstract thì đó là lớp trừu tượng. Nó cần được kế thừa và phương thức của nó được triển khai. Nó không thể được khởi tạo.

Sử dụng từ khóa abstract để khai báo một lớp abstract. Từ khóa này xuất hiện trước từ khóa class trong khai báo lớp. Ví dụ:

abstract class A{}

Có hai cách để đạt được tính trừu tượng hóa trong Java:

  • Lớp abstract (0 tới 100%)
  • Interface (100%)

Phương thức trừu tượng trong Java

Một phương thức được khai báo là abstract và không có trình triển khai thì đó là phương thức trừu tượng.

Nếu bạn muốn một lớp chứa một phương thức cụ thể nhưng bạn muốn triển khai thực sự phương thức đó để được quyết định bởi các lớp con, thì bạn có thể khai báo phương thức đó trong lớp cha ở dạng abstract.

Từ khóa abstract được sử dụng để khai báo một phương thức dạng abstract. Một phương thức abstract không có thân phương thức.

Phương thức abstract sẽ không có định nghĩa, được theo sau bởi dấu chấm phảy, không có dấu ngoặc móc ôm theo sau:

abstract void printStatus(); // Khai bao phuong thuc voi tu khoa abstract va khong co than phuong thuct

Ví dụ về lớp trừu tượng và phương thức trừu tượng trong Java

Trong ví dụ này, Bike là lớp trừu tượng chỉ chứa một phương thức trừu tượng là run. Trình triển khai của nó được cung cấp bởi lớp Honda.

// lop truu tuong Bike abstract class Bike{ abstract void run(); // phuong thuc truu tuong voi tu khoa abstract } // lop Honda4 ke thua lop truu tuong Bike class Honda4 extends Bike{ void run(){ System.out.println("Dang chay mot cach an toan.."); } // phuong thuc main() public static void main(String args[]){ Bike obj = new Honda4(); obj.run(); } }

Kế thừa lớp Abstract trong Java

Trong ví dụ này, Shape là lớp trừu tượng, trình triển khai của nó được cung cấp bởi lớp Rectangle và lớp Circle. Hai lớp này kế thừa lớp trừu tượng Shape.

File: TestAbstraction1.java

// lop truu tuong Shape abstract class Shape{ abstract void draw(); } //Trong tinh huong nay, trinh trien khai duoc cung cap boi ai do, vi du: nguoi su dung cuoi cung nao do class Rectangle extends Shape{ void draw(){ System.out.println("Ve hinh chu nhat"); } } class Circle1 extends Shape{ void draw(){ System.out.println("Ve hinh tron"); } } //Trong tinh huong nay, phuong thuc duoc goi boi lap trinh vien hoac nguoi dung class TestAbstraction1{ public static void main(String args[]){ Shape s=new Circle1(); //Trong tinh huong nay, doi tuong duoc cung cap thong qua phuong thuc, chang han nhu getShape() s.draw(); } }

Khi mình tạo sự thể hiện của lớp Rectangle (tại dòng Shape s=new Circle1();), phương thức draw() của lớp Rectangle sẽ được triệu hồi.

Có thể bạn chưa quen thuộc với cách thức viết chung tất cả các lớp trong cùng một file như trên và có thể làm cho các bạn rối mắt. Trong ví dụ tiếp mình sẽ trình bày riêng rẽ từng file cho các bạn dễ hiểu.

Tất nhiên, trong khi lập trình bất cứ ngôn ngữ nào, mỗi Class mà chúng ta tạo ra đều phục vụ cho một mục đích cụ thể nào đó. Do đó, bạn nên tạo các Class riêng rẽ trong từng file, đừng làm như trên nhé.

Ví dụ khác về Kế thừa lớp Abstract trong Java

Đầu tiên mình có một lớp trừu tượng Bank có phương thức abstract có tên là getRateOfInterest() với mục đích để lấy lãi suất của ngân hàng nói chung.

File: Bank.java

abstract class Bank{ abstract int getRateOfInterest(); }

Tiếp đó, mình có hai lớp SBI và PNB đại diện cho tên các ngân hàng và hai lớp này kế thừa lớp trừu tượng Bank ở trên. Vì hai lớp này kế thừa lớp trừu tượng Bank nên cả hai lớp phải cung cấp trình triển khai cụ thể cho phương thức getRateOfInterest().

File: SBI.java

class SBI extends Bank{ int getRateOfInterest(){return 7;} // bat buoc phai cung cap trinh trien khai cua getRateOfInterest }

File: PNB.java

class PNB extends Bank{ int getRateOfInterest(){return 8;} // bat buoc phai cung cap trinh trien khai cua getRateOfInterest }

Và cuối cùng, lớp TestBank có phương thức main() sẽ có nội dung như sau:

class TestBank{ public static void main(String args[]){ // Tao mot doi tuong SBI moi Bank b=new SBI(); //Neu doi tuong la PNB, phuong thuc cua PNB se duoc trieu hoi int interest=b.getRateOfInterest(); //Trieu hoi phuong thuc cua SBI System.out.println("Ti le lai suat la: "+interest+" %"); }}

Lớp trừu tượng có thể có thành viên dữ liệu, phương thức trừu tượng, constructor, và có thể cả phương thức main().

File: TestAbstraction2.java

//vi du ve lop abstract ma co than phuong thuc abstract class Bike{ Bike(){ System.out.println("bike duoc tao"); } abstract void run(); void changeGear(){ System.out.println("gear duoc thay doi"); } } class Honda extends Bike{ void run(){ System.out.println("dang chay mot cach an toan.."); } } class TestAbstraction2{ public static void main(String args[]){ Bike obj = new Honda(); obj.run(); obj.changeGear(); } }

Qui tắc: Nếu bạn đang kế thừa bất cứ lớp trừu tượng nào mà có phương thức trừu tượng, thì bạn phải hoặc cung cấp trình triển khai của các phương thức của lớp trừu tượng này.

Lớp trừu tượng cũng có thể được sử dụng để cung cấp một số trình triển khai của Interface. Trong tình huống này, người dùng cuối cùng không thể bị bắt buộc phải ghi đè tất cả phương thức của Interface đó.

Ghi chú: Nếu bạn mới học về Java, thì học Interface trước và bỏ qua ví dụ này.

// mot interface A interface A{ void a(); void b(); void c(); void d(); } // lop truu tuong B ke thua interface A abstract class B implements A{ //trong vi du nay, lop truu tuong B co the chi cung cap trinh trien khai phuong thuc c() public void c(){ System.out.println("Toi la C"); } } // lop M ke thua lop truu tuong B class M extends B{ // bat buoc phai trien khai cac phuong thuc a(), b(), c() public void a(){ System.out.println("Toi la a"); } public void b(){ System.out.println("Toi la b"); } public void d(){ System.out.println("Toi la d"); } } // lop Test5 chua phuong thuc main() class Test5{ public static void main(String args[]){ A a=new M(); a.a(); a.b(); a.c(); a.d(); }}

Ps: Đi làm có thể hỏi về sự khác nhau giữa abstract class và interface. Các bạn nên chú ý các phương thức của interface là abstract 100%, trong abstract class có thể có phương thức không phải abstract. Trong thiết kế phần mềm, interface thường được dùng để chỉ 2 hay nhiều class cùng làm việc gì đó (ví dụ cùng in - Printable), trong khi abstract class thường hướng đến quan hệ cha con trong lập trình hướng đối tượng. Các bạn có thể đọc thêm https://stackoverflow.com/questions/479142/when-to-use-an-interface-instead-of-an-abstract-class-and-vice-versa

Abtraction (Trừu tượng) là gì trong Lập trình hướng đối tượng (OOP)

Từ khóa » Các Lớp Trừu Tượng Là Gì