CHÀO! Trong bài học hôm nay, chúng ta sẽ nói về Nguyên tắc lập trình hướng đối tượng. Bạn đã bao giờ tự hỏi tại sao Java được thiết kế chính xác như vậy chưa? Ý tôi là, bạn khai báo các lớp và tạo các đối tượng dựa trên các lớp, các lớp có các phương thức, v.v. Nhưng tại sao ngôn ngữ lại được cấu trúc để các chương trình bao gồm các lớp và đối tượng chứ không phải thứ gì khác? Vì sao khái niệm “đối tượng” được phát minh và đặt lên hàng đầu? Có phải tất cả các ngôn ngữ được thiết kế theo cách này? Nếu không, nó mang lại lợi thế gì cho Java? Như bạn có thể thấy, có rất nhiều câu hỏi :) Chúng ta hãy cố gắng trả lời từng câu hỏi trong bài học hôm nay.
Bạn có thể dễ dàng đọc mã được viết bằng ngôn ngữ này và giải thích một cách khái quát những gì nó làm :)
Lập trình hướng đối tượng (OOP) là gì?
Tất nhiên, Java không được tạo thành từ các đối tượng và lớp chỉ để cho vui. Chúng không phải là ý thích bất chợt của những người tạo ra Java và thậm chí không phải là phát minh của họ. Có nhiều ngôn ngữ khác dựa trên các đối tượng. Ngôn ngữ đầu tiên như vậy được gọi là "Simula". Nó được phát minh vào những năm 1960 ở Na Uy. Hơn nữa, các khái niệm về "lớp" và "phương pháp" đã xuất hiện trong Simula. Theo tiêu chuẩn phát triển phần mềm, "Simula" có vẻ giống như một ngôn ngữ cổ xưa, nhưng bất kỳ ai cũng có thể thấy "sự tương đồng trong gia đình" của nó với Java.
Begin
Class Rectangle (Width, Height); Real Width, Height;
Begin
Real Area, Perimeter;
Procedure Update;
Begin
Area := Width * Height;
OutText("Rectangle is updating, Area = "); OutFix(Area,2,8); OutImage;
Perimeter := 2*(Width + Height);
OutText("Rectangle is updating, Perimeter = "); OutFix(Perimeter,2,8); OutImage;
End of Update;
Update;
OutText("Rectangle created: "); OutFix(Width,2,6);
OutFix(Height,2,6); OutImage;
End of Rectangle;
Rectangle Class ColouredRectangle (Color); Text Color;
Begin
OutText("ColouredRectangle created, color = "); OutText(Color);
OutImage;
End of ColouredRectangle;
Ref(Rectangle) Cr;
Cr :- New ColouredRectangle(10, 20, "Green");
End;
Mã mẫu mã này được lấy từ "Simula - 50 năm OOP" của Weekly-geekly. Như bạn có thể thấy, Java không khác lắm so với ông nội của nó :) Điều này là do sự xuất hiện của Simula đã đánh dấu sự ra đời của một khái niệm mới: lập trình hướng đối tượng. Wikipedia định nghĩa OOP như sau: "Lập trình hướng đối tượng (OOP) là một mô hình lập trình dựa trên khái niệm" đối tượng ", có thể chứa dữ liệu, ở dạng trường (thường được gọi là thuộc tính) và mã, ở dạng thủ tục (thường được gọi là phương pháp)." Theo tôi, đây là một định nghĩa thực sự tốt. Cách đây không lâu, bạn mới bắt đầu học Java, nhưng định nghĩa này có lẽ không chứa bất kỳ từ nào mà bạn không biết :) Ngày nay, OOP là phương pháp lập trình phổ biến nhất. Ngoài Java, Các nguyên tắc OOP được sử dụng trong nhiều ngôn ngữ phổ biến mà bạn có thể đã nghe nói đến. Ví dụ: C ++ (được sử dụng tích cực trong phát triển trò chơi), Objective-C và Swift (được sử dụng để viết chương trình cho thiết bị Apple), Python (phổ biến nhất trong học máy), PHP (một trong những ngôn ngữ phát triển web phổ biến nhất), JavaScript ( dễ dàng hơn để nói nó không được sử dụng để làm gì) và nhiều thứ khác. Vì vậy, các nguyên tắc của OOP là gì? Chúng tôi sẽ cho bạn biết chi tiết. các nguyên tắc của OOP là gì? Chúng tôi sẽ cho bạn biết chi tiết. các nguyên tắc của OOP là gì? Chúng tôi sẽ cho bạn biết chi tiết.
Nguyên tắc OOP
Đây là những nền tảng của nền tảng. 4 tính năng chính cùng nhau tạo thành mô hình lập trình hướng đối tượng. Hiểu chúng là điều cần thiết để trở thành một lập trình viên thành công.Nguyên tắc 1. Kế thừa
Tin vui: bạn đã biết một số nguyên tắc của OOP! :) Chúng tôi đã gặp sự kế thừa một vài lần trong các bài học và chúng tôi đã sử dụng được nó. Kế thừa là một cơ chế cho phép bạn mô tả một lớp mới dựa trên một lớp (cha) hiện có. Khi làm như vậy, lớp mới mượn các thuộc tính và chức năng của lớp cha. Thừa kế để làm gì và nó mang lại lợi ích gì? Trên hết, tái sử dụng mã. Các trường và phương thức được khai báo trong các lớp cha có thể được sử dụng trong các lớp con. Nếu các loại xe đều có 10 trường chung và 5 phương thức giống nhau, bạn chỉ cần chuyển chúng vào Autolớp cha. Bạn có thể sử dụng chúng trong các lớp con cháu mà không gặp vấn đề gì. Ưu điểm vững chắc: cả định lượng (ít mã hơn) và kết quả là định tính (các lớp trở nên đơn giản hơn nhiều). Hơn nữa, tính kế thừa rất linh hoạt — bạn có thể thêm chức năng ghi riêng biệt mà các lớp con bị thiếu (một số trường hoặc hành vi dành riêng cho một lớp cụ thể). Nói chung, cũng như ngoài đời, tất cả chúng ta đều có phần giống bố mẹ mình, nhưng cũng có phần khác với họ :)Nguyên tắc 2. Trừu tượng hóa
Đây là một nguyên tắc rất đơn giản. Trừu tượng có nghĩa là xác định những đặc điểm chính, quan trọng nhất của một thứ gì đó, đồng thời loại bỏ những thứ nhỏ nhặt và không đáng kể. Không cần phải phát minh lại bánh xe. Hãy nhớ lại một ví dụ từ một bài học cũ về các lớp học. Giả sử chúng ta đang tạo một hệ thống nộp hồ sơ cho nhân viên công ty. Để tạo các đối tượng "nhân viên", chúng tôi đã viết một lớp Nhân viên . Những đặc điểm nào là quan trọng để mô tả chúng trong hệ thống hồ sơ của công ty? Tên, ngày sinh, SSN và ID nhân viên. Nhưng không chắc là chúng ta sẽ cần chiều cao, màu mắt hoặc màu tóc của nhân viên cho loại hồ sơ này. Công ty không cần những thông tin như vậy về một nhân viên. Vì vậy, trong lớp Nhân viên , chúng tôi khai báo các biến sau:, int age , int socialSecurityNumber và int employeeId . Và chúng tôi trừu tượng hóa thông tin không cần thiết như màu mắt. Tuy nhiên, nếu chúng tôi đang tạo một hệ thống lưu trữ cho một công ty quản lý người mẫu, thì tình hình sẽ thay đổi đáng kể. Chiều cao, màu mắt và màu tóc của người mẫu là những đặc điểm quan trọng, nhưng SSN của cô ấy hoàn toàn không liên quan đến chúng tôi. Vì vậy, trong lớp Model , chúng ta tạo các biến sau: Chiều cao chuỗi , Tóc chuỗi , Mắt chuỗi .Nguyên tắc 3. Đóng gói
Chúng tôi đã chạy vào điều này. Trong Java, đóng gói có nghĩa là hạn chế khả năng đọc và thay đổi dữ liệu. Như bạn có thể thấy, thuật ngữ này dựa trên từ "viên nang". Chúng tôi sẽ sử dụng một "viên nang" để ẩn một số dữ liệu quan trọng mà chúng tôi không muốn người khác thay đổi. Đây là một ví dụ đơn giản từ cuộc sống thực. Bạn có tên và họ. Tất cả bạn bè của bạn đều biết họ. Nhưng họ không có khả năng thay đổi tên hoặc họ của bạn. Chúng tôi có thể nói rằng quy trình thực hiện điều đó được "gói gọn" bởi hệ thống tòa án: bạn chỉ có thể thay đổi họ của mình thông qua thư ký tòa án và chỉ bạn mới có thể thực hiện việc đó. Những "người dùng" khác có quyền truy cập "chỉ đọc" đối với họ và tên của bạn :) Một ví dụ minh họa khác là tiền mặt được giữ ở nhà. Để nó ở nơi dễ thấy ở giữa phòng của bạn không phải là một ý kiến hay. Bất kỳ "người dùng" nào (người đến nhà bạn) sẽ có thể thay đổi số tiền của bạn, tức là họ có thể lấy tiền của bạn. Sẽ tốt hơn nếu gói gọn nó trong két sắt. Sau đó, quyền truy cập sẽ chỉ dành cho bạn và chỉ bằng cách sử dụng một mã đặc biệt. Các ví dụ rõ ràng về tính đóng gói mà bạn đã làm việc là các công cụ sửa đổi quyền truy cập (riêng tư, công khai, v.v.), cũng như các trình cài đặt và trình thu thập. Nếu bạn không gói gọntrường tuổi của lớp mèo thì bất kỳ ai cũng có thể viết:
Cat.age = -1000;
Cơ chế đóng gói cho phép chúng tôi bảo vệ trường tuổi bằng phương thức setter, trong đó chúng tôi có thể đảm bảo rằng tuổi không thể được đặt thành số âm.
Nguyên tắc 4. Đa hình
Đa hình là khả năng làm việc với một số loại như thể chúng là cùng một loại. Hơn nữa, hành vi của các đối tượng sẽ khác nhau tùy thuộc vào loại của chúng. Điều đó nghe có vẻ phức tạp phải không? Hãy hiểu ý nghĩa của nó ngay bây giờ. Lấy ví dụ đơn giản nhất: động vật. Tạo một lớp Animal với một phương thức speak() duy nhất và hai lớp con - Cat và Dog .
public class Animal {
public void speak() {
System.out.println("Hello!");
}
}
public class Dog extends Animal {
@Override
public void speak() {
System.out.println ("Woof-woof!");
}
}
public class Cat extends Animal {
@Override
public void speak() {
System.out.println("Meow!");
}
}
Bây giờ chúng ta sẽ thử khai báo một biến tham chiếu Animal và gán một đối tượng Dog cho nó.
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.speak();
}
}
Phương pháp nào bạn nghĩ sẽ được gọi? Animal.speak() hay Dog.speak() ? Phương thức trong lớp Dog sẽ được gọi là: Woof-woof! Chúng tôi đã tạo một tham chiếu Động vật , nhưng đối tượng hoạt động giống như một Con chó . Nếu cần thiết, nó có thể cư xử như một con mèo, ngựa hoặc một số động vật khác. Điều quan trọng là gán một lớp con cụ thể cho biến tham chiếu Động vật chung . Điều này có ý nghĩa, bởi vì tất cả các con chó là động vật. Đó là những gì chúng tôi đã nghĩ đến khi nói "hành vi của các đối tượng sẽ khác nhau tùy thuộc vào loại của chúng." Nếu chúng ta tạo một đối tượng Cat ...
public static void main(String[] args) {
Animal cat = new Cat();
cat.speak();
}
phương thức speak () sẽ hiển thị "Meow!" Nhưng 'khả năng làm việc với một số loại như thể chúng là cùng một loại' có nghĩa là gì? Điều này cũng khá đơn giản. Hãy tưởng tượng rằng chúng ta đang tạo một tiệm hớt tóc cho động vật. Tiệm cắt tóc của chúng ta có thể cắt tỉa lông cho bất kỳ con vật nào, vì vậy chúng ta tạo một phương thức trim() với tham số Animal (con vật đang được cắt tóc).
public class AnimalBarbershop {
public void trim(Animal animal) {
System.out.println("The haircut is done!");
}
}
Và bây giờ chúng ta có thể truyền các đối tượng Cat và Dog cho phương thức trim() !
public static void main(String[] args) {
Cat cat = new Cat();
Dog dog = new Dog();
AnimalBarbershop barbershop = new AnimalBarbershop();
barbershop.trim(cat);
barbershop.trim(dog);
}
Và đây là ví dụ rõ ràng: lớp AnimalBarbershop làm việc với các kiểu Mèo và Chó như thể chúng là cùng một kiểu. Đồng thời, Mèo và Chó có những hành vi khác nhau: mỗi người nói một cách khác nhau.
GO TO FULL VERSION