JavaRush /Java Blog /Random-KO /게터 및 세터

게터 및 세터

Random-KO 그룹에 게시되었습니다
안녕하세요! 이전 강의에서는 필드와 메서드를 사용하여 자신만의 본격적인 클래스를 만드는 방법을 이미 배웠습니다. 이것은 심각한 진전입니다. 잘했습니다! 하지만 이제 나는 여러분에게 불쾌한 진실을 말해야 합니다. 우리는 수업을 제대로 만들지 않았습니다! 왜? 언뜻 보면 이 클래스에는 오류가 없습니다.
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!");
   }
}
실제로 그렇습니다. 직장에 앉아 Cat고양이를 나타내는 이와 같은 클래스를 작성했다고 상상해 보세요. 그리고 그는 집에 갔다. 당신이 없는 동안 다른 프로그래머가 일하러 와서 자신의 클래스를 만들었고 Main, 그곳에서 그는 당신이 작성한 클래스를 사용하기 시작했습니다 Cat.
public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
그가 왜 그랬는지, 어떻게 일어났는지는 중요하지 않습니다. 어쩌면 그 사람이 피곤했거나 잠을 충분히 자지 못했을 수도 있습니다. 또 다른 중요한 점은 현재 클래스를 사용하면 Cat필드에 이상한 값을 할당할 수 있다는 것입니다. 결과적으로 프로그램에는 -1000년 된 고양이와 같이 잘못된 상태의 개체가 포함되어 있습니다. 우리는 결국 어떤 실수를 하게 됐나요? 클래스를 만들 때 해당 데이터를 노출했습니다. 필드 nameageweight공개 도메인에 있습니다. 프로그램의 어느 곳에서나 접근할 수 있습니다. 객체를 생성하기만 하면 됩니다 . 모든 프로그래머는 " " 연산자 Cat를 통해 해당 데이터에 직접 접근할 수 있습니다..
Cat cat = new Cat();
cat.name = "";
여기서는 필드에 직접 액세스하여 name해당 값을 설정합니다. 우리는 잘못된 외부 간섭으로부터 어떻게든 데이터를 보호해야 합니다. 이를 위해 무엇이 필요합니까? 먼저, 모든 인스턴스 변수(필드)는 수정자로 표시되어야 합니다 private. Private은 Java에서 가장 엄격한 액세스 수정자입니다. 이를 사용하면 클래스 Cat외부에서 클래스 필드에 액세스할 수 없습니다.
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 name field in the Cat class has private access!
   }
}
컴파일러는 이를 보고 즉시 오류를 생성합니다. 이제 필드가 보호되는 것 같습니다. 그러나 그들에 대한 접근은 "단단히" 닫혀 있는 것으로 밝혀졌습니다. 필요한 경우 프로그램은 기존 고양이의 무게조차 얻을 수 없습니다. 이것은 또한 선택 사항이 아닙니다. 이 형식에서는 우리 클래스를 사용하는 것이 사실상 불가능합니다. 이상적으로는 데이터에 대한 일종의 제한된 액세스를 허용해야 합니다.
  • 다른 프로그래머도 객체를 생성할 수 있어야 합니다.Cat
  • 이미 존재하는 개체에서 데이터를 읽을 수 있어야 합니다(예: 이미 존재하는 고양이의 이름이나 나이를 가져옴).
  • 필드 값을 할당하는 것도 가능해야 합니다. 그러나 동시에 올바른 값만 있습니다. 객체는 잘못된 객체로부터 보호되어야 합니다("연령 = -1000년" 등은 안 됨).
요구 사항 목록은 괜찮습니다! 그러나 실제로 이 모든 것은 gettersetter 라는 특별한 방법을 사용하여 쉽게 달성할 수 있습니다 .
게터 및 세터 - 2
이름은 영어 " get " - " receive "(즉, "필드 값을 가져오는 방법") 및 set - " set "(예: "필드 값을 설정하는 방법")에서 유래되었습니다. 우리 클래스를 예로 들어 그들이 어떻게 보이는지 살펴보겠습니다 Cat.
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;
   }
}
보시다시피 모든 것이 매우 간단합니다 :) 이름은 대부분 get/set 라는 단어 + 담당하는 필드 이름으로 구성됩니다. 예를 들어, 메소드는 호출된 객체의 getWeight()필드 값을 반환합니다 . weight프로그램에서 보면 다음과 같습니다.
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);
       String barsikName = barsik.getName();
       int barsikAge = barsik.getAge();
       int barsikWeight = barsik.getWeight();

       System.out.println("Cat name: " + barsikName);
       System.out.println("Cat's age: " + barsikAge);
       System.out.println("Weight of the cat: " + barsikWeight);
   }
}
콘솔 출력:

Name кота: Барсик
Возраст кота: 5
Вес кота: 4
이제 다른 클래스( Main)에서 필드에 액세스할 수 Cat있지만 getter를 통해서만 가능합니다 . getter에는 액세스 한정자가 있다는 점에 유의하세요 public. 이는 프로그램의 어느 곳에서나 액세스할 수 있음을 의미합니다. 가치를 할당하는 것은 어떻습니까? Setter 메소드가 이를 담당합니다.
public void setName(String name) {
   this.name = name;
}
보시다시피 그들의 작업도 간단합니다. setName()객체에 대한 메소드를 호출하고 Cat문자열을 인수로 전달하면 이 문자열이 name객체의 필드에 할당됩니다.
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);

       System.out.println("The original name of the cat is " + barsik.getName());
       barsik.setName("Basil");
       System.out.println("The new name of the cat -" + barsik.getName());
   }
}
여기서는 getter와 setter를 모두 사용했습니다. 먼저 getter를 사용하여 고양이의 초기 이름을 수신하여 콘솔에 출력했습니다. 그런 다음 setter를 사용하여 name해당 필드에 "Vasily"라는 새 값이 할당되었습니다. 그런 다음 getter를 사용하여 이름이 실제로 변경되었는지 확인하기 위해 다시 이름을 얻었습니다. 콘솔 출력:

Изначальное Name кота — Барсик
Новое Name кота — Васorй
차이점은 무엇입니까? setter가 있더라도 객체 필드에 잘못된 값을 할당할 수도 있습니다.
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);
       barsik.setAge(-1000);

       System.out.println("Age of Barsik -" + barsik.getAge() + " years");
   }
}
콘솔 출력:

Возраст Барсика — -1000 лет
차이점은 setter가 완전한 방법이라는 것입니다 . 그리고 메서드에는 필드와 달리 허용되지 않는 값을 방지하는 데 필요한 확인 논리를 넣을 수 있습니다. 예를 들어 나이에 음수를 할당하는 것을 쉽게 비활성화할 수 있습니다.
public void setAge(int age) {
   if (age >= 0) {
       this.age = age;
   } else {
       System.out.println("Error! Age cannot be negative!");
   }
}
이제 우리 코드가 올바르게 작동합니다!
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);
       barsik.setAge(-1000);

       System.out.println("Age of Barsik -" + barsik.getAge() + " years");
   }
}
콘솔 출력:

Ошибка! Возраст не может быть отрицательным числом!
Возраст Барсика — 5 лет
setter 내부에는 제한 사항이 있으며 잘못된 데이터를 설정하려는 시도로부터 보호합니다. Barsik의 나이는 변하지 않았습니다. Getter와 Setter는 항상 생성되어야 합니다. 필드에 가능한 값에 대한 제한이 없더라도 이로 인한 피해는 없습니다. 상황을 상상해 보십시오. 귀하와 동료가 함께 프로그램을 작성하고 있습니다. 공개 필드가 있는 클래스를 만들었고 Cat모든 프로그래머가 원하는 대로 이를 사용합니다. 그러던 어느 날 문득 이런 생각이 들었습니다. “젠장, 조만간 누군가가 실수로 변수에 음수를 할당할 수도 있습니다 weight! 세터를 만들고 모든 필드를 비공개로 설정해야 합니다!” 당신이 코드를 생성하면 동료가 작성한 모든 코드가 즉시 중단됩니다. 결국, 그들은 이미 필드에 직접 액세스하는 많은 코드를 작성했습니다 Cat.
cat.name = "Hippopotamus";
이제 필드가 비공개가 되었고 컴파일러에서 많은 오류가 발생했습니다!
cat.name = "Hippopotamus";//error! The name field of the Cat class has private access!
그러한 상황에서는 처음부터 필드를 숨기고 getter-setter를 생성하는 것이 좋습니다 . 모든 동료가 이를 사용하게 되며, 필드 값을 제한해야 한다는 사실을 늦게 깨달은 경우 간단히 setter 내부에 확인을 추가하기만 하면 됩니다. 그리고 누구도 이미 작성된 코드를 깨뜨리지 않을 것입니다. 물론 특정 필드에 대한 읽기 전용 액세스를 원하는 경우 해당 필드에 대해 하나의 getter를 만들 수 있습니다. “Outside”, 즉 클래스 외부에서는 메서드만 사용할 수 있어야 합니다. 데이터는 숨겨져 있어야 합니다.
게터 및 세터 - 4
휴대폰으로 비유할 수 있습니다. 일반 휴대전화를 켜는 대신 모든 전선, 회로 등이 들어 있는 열린 케이스가 있는 휴대전화를 받았다고 상상해 보세요. 튀어 나와. 전화는 작동합니다. 다이어그램을 열심히 만지작거리면 전화를 걸 수도 있습니다. 하지만 아마 그냥 깨뜨릴 것입니다. 대신 제조 회사는 인터페이스를 제공합니다. 고객이 필요한 번호로 전화를 걸고 핸드셋으로 녹색 버튼을 누르면 통화가 시작됩니다. 그리고 그는 회로와 전선 내부에서 무슨 일이 일어나고 있는지, 그리고 그들이 어떻게 작업을 수행하는지 신경 쓰지 않습니다. 이 예에서 회사는 전화기의 "내부"(데이터)에 대한 액세스를 제한하고 외부에는 인터페이스(메서드)만 남겨 두었습니다. 결과적으로 고객은 원하는 것을 얻을 수 있으며(전화 걸기) 내부의 어떤 것도 깨지지 않을 것입니다.
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION