CodeGym /Blog Java /Ngẫu nhiên /Nguyên tắc OOP

Nguyên tắc OOP

Xuất bản trong nhóm
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.

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. Nguyên lý lập trình hướng đối tượng - 1Bạ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 :)

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 socialSecurityNumberint 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 - CatDog .

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 CatDog 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èoChó như thể chúng là cùng một kiểu. Đồng thời, MèoChó có những hành vi khác nhau: mỗi người nói một cách khác nhau.

Tại sao chúng ta cần OOP?

Tại sao OOP lại xuất hiện như một khái niệm lập trình mới? Các lập trình viên có các công cụ hoạt động, chẳng hạn như ngôn ngữ thủ tục. Điều gì đã thúc đẩy họ phát minh ra một cái gì đó mới về cơ bản? Trên tất cả, sự phức tạp của các nhiệm vụ mà họ phải đối mặt. Nếu 60 năm trước, nhiệm vụ của lập trình viên là "đánh giá một số biểu thức toán học", thì bây giờ, nó có thể là "thực hiện 7 kết thúc khác nhau cho trò chơi STALKER, tùy thuộc vào sự kết hợp các quyết định của người chơi tại các điểm A, B, C, DE , và F trong trò chơi." Như bạn có thể thấy, các nhiệm vụ rõ ràng đã trở nên phức tạp hơn trong những thập kỷ qua. Và kết quả là các kiểu dữ liệu trở nên phức tạp hơn. Đây là một lý do khác khiến OOP xuất hiện. Một biểu thức toán học có thể được đánh giá dễ dàng bằng cách sử dụng các nguyên hàm thông thường. Không có đối tượng là cần thiết ở đây. Nhưng nhiệm vụ với kết thúc trò chơi thậm chí sẽ khó mô tả nếu không sử dụng các lớp tùy chỉnh. Điều đó nói rằng, khá dễ dàng để mô tả nó bằng cách sử dụng các lớp và đối tượng. Rõ ràng, chúng ta sẽ cần một số lớp: Game, Stalker, Ending, PlayerDecision, GameEvent, v.v. Nói cách khác, ngay cả khi không bắt tay vào giải quyết vấn đề, chúng ta vẫn có thể dễ dàng “vẽ ra” một giải pháp trong đầu. Độ phức tạp ngày càng tăng của các nhiệm vụ buộc các lập trình viên phải chia chúng thành nhiều phần. Nhưng điều này không dễ thực hiện trong lập trình thủ tục. Và khá thường xuyên, một chương trình giống như một cái cây với rất nhiều nhánh đại diện cho tất cả các đường dẫn thực hiện có thể. Tùy thuộc vào các điều kiện nhất định, một nhánh của chương trình hay nhánh khác đã được thực thi. Đối với các chương trình nhỏ, điều này thuận tiện, nhưng rất khó để chia một vấn đề lớn thành các phần. Đây là một lý do khác cho sự xuất hiện của OOP. Mô hình này cho phép các lập trình viên chia chương trình thành nhiều "mô-đun" (lớp), mỗi mô-đun thực hiện phần công việc riêng của mình. Bằng cách tương tác với nhau, tất cả các đối tượng hoàn thành công việc của chương trình của chúng tôi. Ngoài ra, chúng tôi có thể sử dụng lại mã của mình ở nơi khác trong chương trình, điều này cũng tiết kiệm rất nhiều thời gian.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION