CodeGym/Blog Java/Ngẫu nhiên/Getters và setters

Getters và setters

Xuất bản trong nhóm
Xin chào! Trong các phần trước, bạn đã học cách khai báo các lớp chính thức của riêng mình bằng các phương thức và trường. Trong bài học hôm nay, chúng ta sẽ nói về Getters và Setters trong Java. Đây là tiến bộ nghiêm túc, được thực hiện tốt! Nhưng bây giờ tôi phải nói với bạn một sự thật khó chịu. Chúng tôi đã không khai báo chính xác các lớp học của mình! Tại sao? Thoạt nhìn, lớp sau không có bất kỳ sai lầm nào:
public class Cat {

   public String name;
   public int age;
   public int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }
}
Nhưng nó có. Hãy tưởng tượng bạn đang ngồi làm việc và viết lớp Cat này để đại diện cho những chú mèo. Và sau đó bạn về nhà. Trong khi bạn đi vắng, một lập trình viên khác đến làm việc. Anh ấy tạo lớp Chính của riêng mình , nơi anh ấy bắt đầu sử dụng lớp Cat mà bạn đã viết.
public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
Không quan trọng tại sao anh ta làm điều đó và nó xảy ra như thế nào (có thể anh ta mệt mỏi hoặc ngủ không đủ giấc). Một vấn đề khác quan trọng: lớp Cat hiện tại của chúng tôi cho phép các trường được gán các giá trị hoàn toàn điên rồ. Do đó, chương trình có các đối tượng có trạng thái không hợp lệ (chẳng hạn như con mèo -1000 tuổi này). Vậy chúng ta đã mắc lỗi gì khi khai báo lớp của mình? Chúng tôi đã tiết lộ dữ liệu của lớp mình. Các trường tên, tuổi và cân nặng được công khai. Chúng có thể được truy cập ở bất cứ đâu trong chương trình: chỉ cần tạo một đối tượng Cat và bất kỳ lập trình viên nào cũng có quyền truy cập trực tiếp vào dữ liệu của nó thông qua toán tử dấu chấm ( . )
Cat cat = new Cat();
cat.name = "";
Ở đây chúng tôi đang truy cập trực tiếp vào trường tên và đặt giá trị của nó. Chúng ta cần bằng cách nào đó bảo vệ dữ liệu của mình khỏi sự can thiệp không phù hợp từ bên ngoài. Chúng ta cần gì để làm điều đó? Đầu tiên, tất cả các biến thể hiện (trường) phải được đánh dấu bằng công cụ sửa đổi riêng. Riêng tư là công cụ sửa đổi truy cập nghiêm ngặt nhất trong Java. Khi bạn làm điều này, các trường của lớp Cat sẽ không thể truy cập được bên ngoài lớp.
public class Cat {

   private String name;
   private int age;
   private int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";//error! The Cat class's name field is private!
   }
}
Trình biên dịch nhìn thấy điều này và ngay lập tức tạo ra lỗi. Bây giờ các lĩnh vực được sắp xếp bảo vệ. Nhưng hóa ra có lẽ chúng tôi đã đóng quyền truy cập quá chặt chẽ: bạn không thể lấy trọng lượng của một con mèo hiện có trong chương trình, ngay cả khi bạn cần. Đây cũng không phải là một lựa chọn. Như vậy, lớp của chúng tôi về cơ bản là không sử dụng được. Lý tưởng nhất là chúng ta cần cho phép một số loại truy cập hạn chế:
  • Các lập trình viên khác có thể tạo các đối tượng Cat
  • Họ có thể đọc dữ liệu từ các đối tượng hiện có (ví dụ: lấy tên hoặc tuổi của một con mèo hiện có)
  • Cũng có thể gán giá trị trường. Nhưng khi làm như vậy, chỉ các giá trị hợp lệ mới được phép. Các đối tượng của chúng ta phải được bảo vệ khỏi các giá trị không hợp lệ (ví dụ: tuổi = -1000, v.v.).
Đó là một danh sách hợp lý các yêu cầu! Trong thực tế, tất cả điều này có thể dễ dàng đạt được với các phương thức đặc biệt được gọi là getters và setters.
Getters và setters - 2
Những tên này đến từ "get" (nghĩa là "phương thức lấy giá trị của một trường") và "set" (tức là "phương thức đặt giá trị của một trường”). Hãy xem chúng trông như thế nào trong lớp Cat của chúng ta :
public class Cat {

   private String name;
   private int age;
   private int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }

   public String getName() {
       return name;
   }

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

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       this.age = age;
   }

   public int getWeight() {
       return weight;
   }

   public void setWeight(int weight) {
       this.weight = weight;
   }
}
Như bạn có thể thấy, chúng trông khá đơn giản :) Tên của chúng thường bao gồm "get"/"set" cộng với tên của trường liên quan. Ví dụ, phương thức getWeight() trả về giá trị của trường trọng lượng cho đối tượng mà nó được gọi. Đây là giao diện của nó trong một chương trình:
public class Main {

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5, 4);
       String smudgeName = smudge.getName();
       int smudgeAge = smudge.getAge();
       int smudgeWeight = smudge.getWeight();

       System.out.println("Cat's name: " + smudgeName);
       System.out.println("Cat's age: " + smudgeAge);
       System.out.println("Cat's weight: " + smudgeWeight);
   }
}
Đầu ra bảng điều khiển:
Cat's name: Smudge
Cat's age: 5
Cat's weight: 4
Bây giờ một lớp khác ( Main ) có thể truy cập các trường Cat , nhưng chỉ thông qua getters. Lưu ý rằng getters có công cụ sửa đổi truy cập công khai, nghĩa là chúng có sẵn từ bất kỳ đâu trong chương trình. Nhưng còn việc gán giá trị thì sao? Đây là phương thức setter dành cho
public void setName(String name) {
   this.name = name;
}
Như bạn có thể thấy, chúng cũng đơn giản. Chúng ta gọi phương thức setName() trên đối tượng Cat , chuyển một chuỗi làm đối số và chuỗi được gán cho trường tên của đối tượng.
public class Main {

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5, 4);

       System.out.println("Cat's original name: " + smudge.getName());
       smudge.setName("Mr. Smudge");
       System.out.println("Cat's new name: " + smudge.getName());
   }
}
Ở đây chúng tôi đang sử dụng cả getters và setters. Đầu tiên, chúng tôi sử dụng một getter để lấy và hiển thị tên ban đầu của con mèo. Sau đó, chúng tôi sử dụng một setter để gán một tên mới ("Mr. Smudge"). Và sau đó chúng tôi sử dụng getter một lần nữa để lấy tên (để kiểm tra xem nó có thực sự thay đổi không). Đầu ra bảng điều khiển:
Cat's original name: Smudge
Cat's new name: Mr. Smudge
Vậy sự khác biệt là gì? Chúng tôi vẫn có thể gán các giá trị không hợp lệ cho các trường ngay cả khi chúng tôi có setters:
public class Main {

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5, 4);
       smudge.setAge(-1000);

       System.out.println("Smudge's age: " + smudge.getAge());
   }
}
Đầu ra bảng điều khiển:
Smudge's age: -1000 years
Sự khác biệt là setter là một phương thức chính thức. Và không giống như một trường, một phương thức cho phép bạn viết logic xác minh cần thiết để ngăn các giá trị không được chấp nhận. Ví dụ: bạn có thể dễ dàng ngăn không cho một số âm được gán làm tuổi:
public void setAge(int age) {
   if (age >= 0) {
       this.age = age;
   } else {
       System.out.println("Error! Age can't be negative!");
   }
}
Và bây giờ mã của chúng tôi hoạt động chính xác!
public class Main {

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5, 4);
       smudge.setAge(-1000);

       System.out.println("Smudge's age: " + smudge.getAge());
   }
}
Đầu ra bảng điều khiển:
Error! Age can't be negative!
Smudge's age: 5 years
Bên trong setter, chúng tôi đã tạo một hạn chế để bảo vệ chúng tôi khỏi nỗ lực đặt dữ liệu không hợp lệ. Tuổi của Smudge không thay đổi. Bạn phải luôn tạo getters và setters. Ngay cả khi không có hạn chế về giá trị mà các trường của bạn có thể nhận, các phương thức trợ giúp này sẽ không gây hại gì. Hãy tưởng tượng tình huống sau: bạn và đồng nghiệp của mình đang cùng nhau viết một chương trình. Bạn tạo một lớp Cat với các trường công khai. Tất cả các lập trình viên đang sử dụng chúng theo cách họ muốn. Và rồi một ngày đẹp trời bạn nhận ra: "Chết tiệt, sớm muộn gì ai đó cũng có thể vô tình gán một số âm cho trọng số! Chúng ta cần tạo setters và đặt tất cả các trường ở chế độ riêng tư!" Bạn chỉ cần làm điều đó và ngay lập tức phá vỡ tất cả mã do đồng nghiệp của bạn viết. Rốt cuộc, họtrường mèo trực tiếp.
cat.name = "Behemoth";
Và bây giờ các trường là riêng tư và trình biên dịch tạo ra một loạt lỗi!
cat.name = "Behemoth";//error! The Cat class's name field is private!
Trong trường hợp này, sẽ tốt hơn nếu ẩn các trường và tạo getter và setters ngay từ đầu. Tất cả các đồng nghiệp của bạn sẽ sử dụng chúng. Và nếu bạn nhận ra một cách muộn màng rằng bạn cần hạn chế bằng cách nào đó các giá trị trường, thì bạn có thể chỉ cần viết séc bên trong setter. Và không ai mã sẽ bị phá vỡ. Tất nhiên, nếu bạn muốn quyền truy cập vào một trường chỉ là "chỉ đọc", bạn chỉ có thể tạo một getter cho nó. Chỉ các phương thức nên có sẵn bên ngoài (tức là bên ngoài lớp học của bạn). Dữ liệu nên được ẩn. Chúng ta có thể so sánh với một chiếc điện thoại di động. Hãy tưởng tượng rằng thay vì một chiếc điện thoại di động đi kèm thông thường, bạn được tặng một chiếc điện thoại có vỏ mở, với đủ loại dây, mạch nhô ra, v.v. có khả năng thực hiện cuộc gọi. Nhưng bạn'
Getters và setters - 3
Thay vào đó, nhà sản xuất cung cấp cho bạn một giao diện: người dùng chỉ cần nhập các chữ số chính xác, nhấn nút gọi màu xanh lá cây và cuộc gọi bắt đầu. Cô ấy không quan tâm những gì xảy ra bên trong với các mạch và dây điện, hoặc cách chúng hoàn thành công việc của mình. Trong ví dụ này, công ty giới hạn quyền truy cập vào "bên trong" (dữ liệu) của điện thoại và chỉ hiển thị giao diện (phương thức). Kết quả là người dùng có được thứ mình muốn (khả năng thực hiện cuộc gọi) và chắc chắn sẽ không làm hỏng bất cứ thứ gì bên trong. Để củng cố những gì bạn đã học, chúng tôi khuyên bạn nên xem một video bài học từ Khóa học Java của chúng tôi
Bình luận
  • Phổ biến
  • Mới
Bạn phải đăng nhập để đăng nhận xet
Trang này chưa có bất kỳ bình luận nào