Lập trình hướng đối tượng Java – bạn đã thực sự hiểu rõ?

8
Dịch vụ dạy kèm gia sư lập trình

Trong bài viết này, mình sẽ nói về các khái niệm lập trình hướng đối tượng trong Java. Bởi vì Java như là một hình mẫu lý tưởng cho triết lý lập trình hướng đối tượng.

Vậy lập trình hướng đối tượng là gì? Đó chính là một kiểu lập trình với các khái niệm như Lớp (Class), Đối tượng (Object), Kế thừa (Inheritance), tính đóng gói (Encapsulation), Trừu tượng (Abstraction), Đa hình (Polymorphism) gọi tắt là OOP.

Phần lớn các ngôn ngữ lập trình giống như Java, C++, C#, Ruby… đều theo mô hình lập trình hướng đối tượng.

Qua bài viết này, chúng ta sẽ hiểu rõ bản chất các khái niệm cốt lõi của lập trình hướng đối tượng Java qua 4 tính chất của lập trình hướng đối tượng

  1. Kế thừa
  2. Đóng gói
  3. Trừu tượng
  4. Đa hình

Lập trình hướng đối tượng Java - bạn đã thực sự hiểu rõ?

Trước hết, chúng ta sẽ lướt qua lập trình hướng đối tượng là gì đã nhé!

#Lập trình hướng đối tượng là gì?

Lập trình hướng đối tượng hay còn gọi là lập trình OOP là kỹ thuật lập trình mà tất cả các logic, yêu cầu thực tế đều được xây dựng xoay quanh các đối tượng.

Khi sử dụng OOP, chúng ta sẽ định nghĩa các class để mô hình hóa các đối tượng thực tế. Trong ứng dụng các class sẽ được khởi tạo thành các instance. Trong suốt thời gian ứng dụng chạy, các phương thức (method) của đối tượng này sẽ được gọi.

Trong thế giới thực, đối tượng là những thực thể tồn tại có trạng thái và hành vi.

các phương pháp lập trình hướng đối tượng,

Hướng tiếp cận này hiện đang rất thành công và đã trở thành một trong những khuôn mẫu phát triển phần mềm, đặc biệt là các phần mềm cho doanh nghiệp.

#Ưu điểm của OOP

Do lập trình hướng đối tượng ra đời sau này, nên nó kế thừa và khắc phục được những nhược điểm của các mô hình lập trình trước đó.

Với 4 tính chất OOP đặc thù của mình, có thể nói lập trình hướng đối tượng rất thích hợp cho các ứng dụng dành cho doanh nghiệp.

Mình có thể liệt kê một số ưu điểm của OOP:

  • Khả năng mở rộng cao.
  • Có khả năng tái sử dụng rất tốt nhờ tính kế thừa.
  • Dễ quản lý code khi cần thêm tính năng.
  • Dễ học, đơn giản, dễ bảo trì…

#4 Tính chất của lập trình hướng đối tượng

Chúng ta hãy bắt đầu với khái niệm đầu tiên của lập trình hướng đối tượng: Tính kế thừa

1.Tính kế thừa

Trong lập trình hướng đối tượng, các chương trình máy tính được thiết kế theo nguyên tắc là tất cả mọi thứ đều được xem là đối tượng và tương tác với những đối tượng khác.

Tính kế thừa là một khái niệm được hiểu những thuộc tính của một lớp có thể được kế thừa bởi một lớp khác. Nó giúp chúng ta có thể sử dụng lại code và thiết lập một mối quan hệ giữa các class khác nhau.

Lập trình hướng đối tượng Java - bạn đã thực sự hiểu rõ?

Như chúng ta thấy ở hình trên, một đứa trẻ kế thừa các thuộc tính của cha cậu ấy. Tương tự, trong Java, chúng ta sẽ có 2 class như bên dưới:

  • Lớp cha còn được hiểu là Lớp siêu cấp, Lớp cơ sở (Parent class hoặc Super class hay Base class)
  • Lớp con còn được hiểu Lớp phụ, Lớp dẫn xuất (Child class hoặc Sub class hoặc Derived class)

Một lớp kế thừa những thuộc tính được biết đến là một Sub class trong khi một lớp có các thuộc tính được kế thừa được gọi là Parent class.

Kế thừa được phân chia làm 4 loại:

Lập trình hướng đối tượng Java - bạn đã thực sự hiểu rõ?

Chúng ta hãy bắt đầu với loại đầu tiên của kế thừa: Đơn kế thừa (Single Inheritance)

1.1 Đơn kế thừa (Single Inheritance)

Lập trình hướng đối tượng Java - bạn đã thực sự hiểu rõ?

Đối với Đơn kế thừa, một lớp sẽ kế thừa những thuộc tính của một lớp khác. Nó cho phép một lớp con kế thừa những thuộc tính và hành vi(method) từ một lớp cha.

Điều này sẽ cho phép code khả năng tái sử dụng code cũng như thêm các tính năng mới vào các đoạn code hiện có.

Ở ví dụ bên dưới, Class A là lớp cha và Class B là lớp con với những thuộc tính và hành vi của  lớp cha.

Trong java thì để kế thừa, đơn giản là sử dụng từ khóa extend

Class A
{
---
}
Class B extends A {
---
}

1.2.Kế thừa kiểu Đa cấp (Multilevel Inheritance)

Lập trình hướng đối tượng Java - bạn đã thực sự hiểu rõ?

Khi một lớp được bắt nguồn từ một lớp mà cũng là lớp con (kế thừa từ một lớp khác). Tức là một lớp có nhiều hơn một cấp cha, kiểu kế thừa đó được gọi là kế thừa kiểu Đa cấp.

Hãy xem sơ đồ, Class B kế thừa các thuộc tính và hành vi của class A, và class C kế thừa các thuộc tính, hành vi của Class B. Ở đây, Class A là lớp cha của Class B và Class B là lớp cha của Class C.

Trong trường hợp này, Class C ngầm kế thừa các thuộc tính và hành vi của Class A thông qua Class B. Đó chính là kế thừa kiểu Đa cấp

Cách viết kế thừa kiểu đa cấp trong java cũng tương tự như đơn kế thừa

Class A{
---
}
Class B extends A{
---
}
Class C extends B{
---
}

1.3. Kế thừa thứ bậc (Hierarchical Inheritance)

Lập trình hướng đối tượng Java - bạn đã thực sự hiểu rõ?

Khi một lớp có nhiều hơn một lớp con hoặc nói cách khác là có nhiều hơn một lớp con có cùng chung một lớp cha, lúc này loại kế thừa này được gọi là thứ bậc (hierarchical).

Hãy xem sơ đồ bên trên, Class B and Class C là lớp con đang kế thừa chung lớp cha là Class A.

Cùng xem cấu trúng kế thừa thứ bậc trong Java

Class A{
---
}
Class B extends A{
---
}
Class C extends A{
---
}

1.4. Kế thừa lai (Hybrid Inheritance)

Lập trình hướng đối tượng Java - bạn đã thực sự hiểu rõ?

Kế thừa lai là sự kết hợp của nhiều loại kế thừa và nhiều cấp kế thừa. Vì đa kế thừa không được hỗ trợ trong Java bởi vì nó dẫn đến sự mơ hồ, nên loại kế thừa này chỉ có thể thực hiện được thông qua Interface

Hãy xem sơ đồ trên, Class A là lớp cha của Class B và Class C. Trong khi Class B và Class C đều là lớp cha của Class D

Như vậy, bạn đã hiểu rõ về kế thừa trong lập trình hướng đối tượng rồi đúng không? Hãy cùng chuyển sang một dạng khái niệm lập trình hướng đối tượng khác đó là tính đóng gói (Encapsulation)

2. Tính đóng gói (Encapsulation)

Tính đóng gói là một cơ chế liên kết dữ liệu và code chung với nhau thành một đơn vị duy nhất. Nó cũng được hiểu với mục đích che giấu dữ liệu của bạn để đảm bảo toàn vẹn dữ liệu từ những chỉnh sửa bên ngoài.

Điều này có nghĩa là gì?

Cách tốt nhất để hiểu tính đóng gói là nhìn vào viên nang y tế bên dưới. Ở đây, thuốc luôn được an toàn bên trong viên nang.

Tương tự, thông qua việc đóng gói, các phương thức và biến của một lớp cũng được ẩn và an toàn.

Lập trình hướng đối tượng Java - bạn đã thực sự hiểu rõ?

Chúng ta thực hiện tính đóng gói trong Java bằng cách:

  • Định nghĩa các biến của lớp với phạm vi là private.
  • Chỉ cho phép truy cập vào các thuộc tính/biến của đối tượng thông qua hàm getter, setter.

Hãy xem đoạn code bên dưới để hiểu rõ hơn về tính đóng gói:

public class Employee {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
       this.name = name;
    }

    public static void main(String[] args) {
               // todo
    }
}

 

Mình đã tạo một Class Employee với biến name có phạm vi là private. Sau đó mình đã tạo các phương thức getter và setter. Thông qua đó, chúng ta có thể lấy và gán giá trị cho cho tên của một Employee.

Thông qua các phương thức này, bất kỳ lớp nào muốn truy xuất biến name đều phải sử dụng các phương thức getter và setter mà không thể được phép truy cập trực tiếp vào thuộc tính name

3. Tính trừu tượng (Abstraction)

Tính trừu tượng hướng đến chất lượng của các ý tưởng hơn là các sự kiện. Về cơ bản, tính trừu tượng đề cập đến việc ẩn hay hiện các chi tiết cần thiết cho người dùng.

Hãy tưởng tượng rằng chúng ta có một cuộc gọi, chúng ta chỉ có thể lựa chọn nhấc máy hoặc từ chối cuộc gọi. Nhưng thực tế, có rất nhiều code chạy ngầm bên dưới. Nên bạn không thể biết được quá trình xử lý cuộc gọi, đó chính là ưu điểm của tính trừu tượng.

Do đó, tính trừu tượng giúp chúng ta giảm sự phức tạp. Có hai cách thực hiện tính trừu tượng như bên dưới:

  • Lớp trừu tượng (Abstract Class)
  • Giao diện (Interface)

Lớp trừu tượng (Abstract class)

Lớp trừu tượng trong java chứa từ khóa “abstract”.

Từ khóa abstract là gì? Nếu một lớp được định nghĩa là trừu tượng nó không thể được khởi tạo bằng toán từ “new“, có nghĩa là bạn không thể tạo instance từ một lớp trừu tượng. Ngoài ra, một lớp trừu tượng có thể chứa phương thức trừu tượng hoặc các phương thức bình thường.

Để sử dụng lớp trừu tượng, bắt buộc nó phải được một lớp khác kế thừa và override toàn toàn bộ abstract method .

Giao diện (Interface)

Một Interface trong Java là một tập hợp các phương thức trừu tượng (abstract). Một class triển khai một interface, do đó kế thừa các phương thức abstract của interface.

Một interface không phải là một lớp. Viết một interface giống như viết một lớp, nhưng chúng có 2 định nghĩa khác nhau. Một lớp mô tả các thuộc tính và hành vi của một đối tượng. Một interface chứa các hành vi mà một class triển khai.

Cùng nhau tìm hiểu kỹ hơn về Interface bằng ví dụ ‘ParentCar’ và các phương thức liên quan

public interface ParentCar {
    // Thay đổi số
    public void changeGear( int newValue);
    // tăng tốc
    public void speedUp(int increment);
    // Phanh
    public void applyBrakes(int decrement);
}

Mọi chiếc oto đều có những hàng vi này phải không? Nhưng mỗi loại xe cụ thể lại thực hiện khác nhau

Giả sử bạn đang làm việc với ô tô số sàn, ở đó bạn phải tăng từng số từng cấp một. Nhưng nếu bạn đang làm việc với một chiếc xe tự động, thì hệ thống của bạn sẽ quyết định cách thay đổi số dựa trên đến tốc độ.

Do đó, không phải tất cả các lớp con của mình đều có cùng một logic được viết cho việc thay đổi số.

Tương tự với trường hợp tăng tốc. Giả sử bạn nhấn ga, tốc độ tăng lên10 km hoặc 15km. Nhưng giả sử một ai đó đang lái một chiếc siêu xe và nhấn ga, tốc độ tăng 30kms hoặc 50kms là chắc. Một lần nữa logic thay đổi

Giống như nhấn phanh, một người có thể có một hệ thống phanh mạnh mẽ hoặc không.

Vì tất cả các chức năng đều là common với tất cả các lớp con, nên mình đã tạo interface ‘ParentCar’ có tất các chức năng mà một ôtô đều phải có. Sau đó, từng loại  class ôtô cụ thể sẽ phải thực hiện các hành vi này

public class Audi implements ParentCar {
    int speed = 0;
    int gear = 1;
    public void changeGear(int value) {
        gear = value;
    }
    public void speedUp(int increment) {
        speed = speed + increment;
    }
    public void applyBrakes(int decrement) {
        speed = speed - decrement;
    }
    void printStates() {
        System.out.println("speed:" + speed + "gear:" + gear);
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Audi A6 = new Audi();
        A6.speedUp(50);
        A6.printStates();
        A6.changeGear(4);
        A6.SpeedUp(100);
        A6.printStates();
    }
}

4. Tính đa hình (Polymorphism)

Đa hình có nghĩa là nhiều hình thức, trong đó ‘poly’ có nghĩa là nhiều, còn ‘morph’ có nghĩa là hình thức. Đa hình có thể là một biến, một chức năng hoặc một đối tượng được đưa vào nhiều hình thức.

Nói cách khác, đa hình cho phép bạn định nghĩa một giao diện hoặc một chức năng với nhiều cách cài đặt.

Để  hiểu hơn về đa hình, mình lấy ví dụ như thế này

Lập trình hướng đối tượng Java - bạn đã thực sự hiểu rõ?

Cùng xem xét kịch bản thế giới thực này trong môn cricket, chúng ta đều biết rằng có một số loại người ném banh khác nhau (bowler), ví dụ bowlers nhanh, bowler tốc độ trung bình và xoay.

Như bạn thấy ở hình bên trên, lớp cha BowlerClass có 3 lớp con là FastPacer, MediumPacerSpinner.

Lớp Bower có phương thức bowlingMethod() nơi tất cả các lớp con đều kế thừa phương thức này. Như chúng ta biết, tốc độ một trái banh bánh sẽ khác so với ném trung bình và ném banh xoáy cũng như trong cách chơi và kinh nghiệm của người ném banh,..v.v..

Tương tự như vậy, việc thực hiện bowling của phương thức bowlingMethod() cũng sẽ khác so với những bowler khác. Và cũng tương tự với class spinner.

Điểm chính ở thảo luận trên đơn giản là cùng một tên nhưng có nhiều xử lý khác nhau. Tất cả 3 lớp ở trên đều kế thừa phương thức bowlingMethod() nhưng cách thực hiện của từng lớp là hoàn toàn khác nhau

>>> Tài liệu cho bạn về thuật toán lập trình

Kết luận

Như vậy là mình đã trình bày xong những kiến thức cơ bản nhất để bạn hiểu về lập trình hướng đối tượng Java.

Hi vọng, qua bài viết này bạn sẽ có cái nhìn toàn diện về lập trình java cũng như lập trình hướng đối tượng. Từ đó dễ dàng tiếp cận thế giới lập trình bao la.

Đừng quên like và chia sẻ bài viết nếu thấy có ích nhé.

Chờ chút, nếu bạn muốn học lập trình Java ngay bây giờ và cần tìm một lời khuyên thì của bạn đây: Học lập trình java ở đâu tốt nhất? Có cần phải đến trung tâm học lập trình?

Dịch vụ phát triển ứng dụng mobile giá rẻ - chất lượng
Bài trướcTìm hiểu cách sử dụng promise trong Javascript
Bài tiếp theoNodejs và PHP? Bạn chọn công nghệ web nào?
Tên đầy đủ là Dương Anh Sơn. Tốt nghiệp ĐH Bách Khoa Hà Nội. Mình bắt đầu nghiệp coder khi mà ra trường chẳng xin được việc đúng chuyên ngành. Mình tin rằng chỉ có chia sẻ kiến thức mới là cách học tập nhanh nhất. Các bạn góp ý bài viết của mình bằng cách comment bên dưới nhé !

8
Bình luận. Cùng nhau thảo luận nhé!

avatar
  Theo dõi bình luận  
Mới nhất Cũ nhất Nhiều voted nhất
Thông báo
ánh dương
Guest
ánh dương

Mình đọc thấy nói rằng Java có cơ chế thu gom bộ nhớ tự động nhưng thực sự nó không hiệu quả. Có thể thấy rằng ứng dụng viết bằng java tiêu tốn rất nhiều bộ nhớ nên không thể ca ngợi cái tính năng thu gom rác tự động của nó được. Java chạy trên JVM nên nó chậm. Và tiếc rằng app cho desktop viết bằng java hầu như không có. Bản thân mình thấy C/C++ gọn gàng và quản lý bộ nhớ rất hiệu quả.

Hí
Guest
Hí

Mình có 1 câu hỏi đến nay vẫn chưa tìm ra câu trả lời nào cảm thấy hay. Câu người nói đó là: Theo như định nghĩa bên trên về lập trình OOP: “lập trình OOP là kỹ thuật lập trình mà tất cả các logic, yêu cầu thực tế đều được xây dựng xoay quanh các đối tượng.” Thì Java k phải là ngôn ngữ lập trình hướng đối tượng vì nó có support những primitive type giống như là int, long, float… và chúng ta có thể tạo ra những phép toàn logic dựa vào những kiểu này… Đọc thêm »

M-T
Guest
M-T

Học code ra trường được 2 năm, không đủ kiến thức để đi xin việc ngành mình học làm bảo hành cho 1 công ty điện tử, giờ đang học lại java core-> web, đầu năm sau đi xin việc đọc được bài này cũng thấy hay. Thích này này của ad.”Tên đầy đủ là Dương Anh Sơn. Tốt nghiệp ĐH Bách Khoa Hà Nội. Mình bắt đầu nghiệp coder khi mà ra trường chẳng xin được việc đúng chuyên ngành(Ngành kéo cáp và trèo cột). Mình tin rằng chỉ có chia sẻ kiến thức mới là cách học tập… Đọc thêm »

Phúc
Guest
Phúc

Trong câu “Như bạn thấy ở hình bên trên, có 3 lớp cha là BowlerClass” theo ví dụ thì chỉ có 1 lớp cha là BowlerClass.

Nam Tôi
Member
Nam Tôi

trên lý thuyết thì bài viết có thể giúp người đọc hiểu rõ được bản chất gần như quan trọng nhất đó là đa hình( (theo cảm nhận của mình nó là khó nhất trong OOP vì khi triển khai đa hình trong 1 bài tập thực tế rất khó hiểu cho những bạn mới tiếp xúc)