접근 제어자
- 접근 제어자의 목적 : 멤버 또는 클래스에 사용 → 해당 멤버 또는 클래스를 외부에서 접근하지 못하도록 제한하는 역할
- 접근 범위가 넓은 쪽에서 좁은 쪽의 순
: public > protected > (default) > private
① public : 접근 제한 없음
② (default) : 같은 패키지 내에서만 접근 가능 → 접근 제어자가 지정되어 있지 않은 경우에 해당
③ protected : 같은 패키지 내 또는 다른 패키지의 자손 클래스에서 접근 가능
④ private : 같은 클래스 내에서만 접근 가능
캡슐화 ( encapsulation )
- 외부로부터 데이터를 보호하기 위해 멤버 변수의 값에 직접적으로 접근하지 않은 것이 보안상 좋음
- 데이터가 유효한 값을 유지하도록, 외부로부터의 접근을 제한하는 것이 필요
→ 멤버변수를 private나 protected로 제한하고,
메서드를 public으로 지정해 메서드를 통해 간접적으로 멤버 변수의 값을 읽고 변경하는 것이 바람직
- 속성( property ) 함수
① getter : get멤버변수이름
→ 멤버변수의 값을 읽는 메서드
② setter : set멤버변수이름
→ 멤버변수의 값을 변경하는 메서드
· 오른쪽 클릭 → Source → Generate Getter / Setter → 외부에서 접근하게 할 변수만 체크 후, Finish
▷ 첫번째 예시
< 데이터 클래스 >
package human;
public class Human {
// 1. 멤버(필드, 속성) : 키, 몸무게, 성별
double height;
double weight;
char gender;
// 2. 속성함수 이용 -> 데이터에 직접적인 접근 제한하기
// 데이터의 값을 변경하는 set메소드
void setheight(double height) {
this.height = height; // 인스턴스 변수와 지역변수를 구분하기 위해 객체 자신을 의미하는 this 사용
}
// 데이터의 값을 읽어오는 get메소드
double getheight() {
return this.height;
}
void setweight(double weight) {
this.weight = weight;
}
double getweight() {
return this.weight;
}
void setgender(char gender) {
this.gender = gender;
}
char getgender() {
return this.gender;
}
// 3. 기본생성자 생성 : 객체 초기화 시, default값으로 설정
Human() {
this.height = 150;
this.weight = 50;
this.gender = '여';
}
❶ 멤버 변수 선언
❷ 속성함수 ( set메소드, get메소드 )를 이용해 데이터에 직접적인 접근을 제한 → 외부로부터 데이터 보호
❸ 기본생성자 생성 → 객체가 생성될 때마다 생성자가 호출되어 객체의 초기화 담당
< 실행 클래스 >
package human;
public class HumanApp {
public static void main(String[] args) {
// 1. 실제 객체(Object) 탄생
Human human = new Human();
// 2. 현재 human 객체의 상태를 알아보자. (=정보출력)
System.out.printf("human의 키 %.1f cm", human.getheight());
System.out.printf("\nhuman의 몸무게 %.1f kg", human.getweight());
System.out.printf("\nhuman의 성별 %c", human.getgender());
System.out.println("\n입니다.");
System.out.println("--------------------------------------");
// 3. 외부 클래스에서 참조변수를 이용해 간접적으로 데이터 값 변경하기
// 키 설정
human.setheight(180);
// 몸무게 설정
human.setweight(80);
// 성별 설정
human.setgender('남');
// 4. 변경한 데이터 값 출력하기
System.out.printf("human의 키 %.1f cm", human.getheight());
System.out.printf("\nhuman의 몸무게 %.1f kg", human.getweight());
System.out.printf("\nhuman의 성별 %c", human.getgender());
System.out.println("\n입니다.");
❶ 객체 생성
❷ 객체의 현재 데이터 출력
❸ set메소드를 이용해 간접적으로 데이터의 값을 변경
❹ get메소드를 이용해 데이터의 값을 불러 출력하기
< 개선할 점 >
실행 클래스에서 데이터의 값을 변경 후, 출력할 때마다 동일한 출력 메소드를 반복해야 함
→ 데이터 클래스에 출력 메서드를 따로 생성시킨 후, 메서드 호출을 통해 출력시키자.
< 데이터 클래스 >
// 3. 출력 메소드 printInfo 생성
void printInfo(){
System.out.printf("human의 키 %.1f cm", this.getheight());
System.out.printf("\nhuman의 몸무게 %.1f kg", this.getweight());
System.out.printf("\nhuman의 성별 %c", this.getgender());
System.out.println("\n입니다.");
}
< 실행 클래스 >
// printInfo() 메서드 호출로 새로운 데이터 값 출력
human.printInfo();
< 출력 결과 >
human의 키 150.0 cm
human의 몸무게 50.0 kg
human의 성별 여
입니다.
--------------------------------------
human의 키 180.0 cm
human의 몸무게 80.0 kg
human의 성별 남
입니다.
∴ 메소드를 통해 데이터에 간접적으로 접근하므로 외부로부터 데이터를 보호할 수 있음
따로 출력하는 메소드를 생성해서 메소드 호출로 객체 정보를 출력하니 코드가 훨씬 간결해짐을 알 수 있음
▷ 두번째 예시
< 데이터 클래스 >
package human;
public class Me {
// 1. 멤버변수 선언
double height;
double weight;
char gender;
String name;
String phone;
// 2. 속성함수 이용 - setter, getter
void setheight(double height) {
this.height = height;
}
double getheight() {
return this.height;
}
void setweight(double weight) {
this.weight = weight;
}
double getweight() {
return this.weight;
}
void setgender(char gender) {
this.gender = gender;
}
char getgender() {
return this.gender;
}
void setname(String name) {
this.name = name;
}
String getname() {
return this.name;
}
void setphone(String phone) {
this.phone = phone;
}
String getphone() {
return this.phone;
}
// 3. 사용자 정의 기본생성자 생성
private Me (){
this.height = 150;
this.weight = 50;
this.gender = '여';
this.name = "";
this.phone = "";
}
❶ 멤버 변수 선언 : Human 클래스에 필수 데이터인 이름과 폰번호의 변수를 추가함
( 필수 데이터 : name, phone / 기본 데이터 : height, weight, gender )
❷ 속성함수 ( set메소드, get메소드 )를 이용해 데이터에 직접적인 접근을 제한 → 외부로부터 데이터 보호
❸ 기본생성자 생성 : 접근제어자 private로 제한 ( Me 클래스에서만 접근 가능 )
∵ 환상 데이터이므로 외부에서 호출 금지
명시적으로 객체를 생성한 후, 비어있음이란 뜻으로 해석 → 나중에 데이터 내용 설정 가능
< 실행 데이터 >
package human;
public class MeApp {
public static void main(String[] args) {
// 1. 객체 생성
Me me = new Me();
}
Error ) The constructor Me() is not visible.
∵ 데이터 클래스에서 기본생성자 Me( )가 private로 설정되었기 때문에 외부 클래스인 MeApp에서 호출할 수 없음
▶ 필수 데이터만 출력하기
< 데이터 클래스 >
// 4. 필수 필드용 생성자
Me(String name, String phone){
this();
this.name = name;
this.phone = phone;
}
// 5. 필수 데이터만 출력하는 메서드
void printInfo() {
System.out.printf("\n나의 이름 %s ", this.getname());
System.out.printf("\n나의 전화번호 %s ", this.getphone());
}
❹ 필수 필드용 생성자 생성
❺ 필수 데이터만 출력하는 메서드 생성
< 실행 데이터 >
// 2. 필수 필드용 생성자 호출
Me me = new Me("홍길동", "010-1234-5678");
me.printInfo();
< 출력 결과 >
나의 이름 홍길동
나의 전화번호 010-1234-5678
4-1. 필수 필드용 생성자에서 첫번째 this(); 는 3. 사용자 정의 기본생성자 호출을 의미
→ 3. 사용자 정의 기본생성자의 접근제어자가 private로 지정되어 있기 때문에 기본 데이터가 출력되지 않음.
▶ 필수 데이터는 항상 출력되고, 기본 데이터는 선택적으로 출력해보기
→ 메소드를 따로 생성해 해당 메소드를 출력하면 되지만, 프로그래밍의 경우 최대한 코드의 중복을 제거하고자 함
∴ 메소드 오버로딩 이용해 중복없이 코드를 더 간결하게 작성
- 메소드 오버로딩 ( overloading )
: 한 클래스 내에 같은 이름의 메서드를 여러 개 정의하는 것
· 조건
① 메서드 이름이 같아야 함
② 매개변수의 개수 또는 타입이 달라야 함
③ 반환 타입은 관계없음
· 오버로딩된 메소드를 호출할 경우, JVM이 매개값의 타입을 보고 호출할 메서드 선택
JVM은 반환타입을 보고 메소드를 선택하지 않기 때문에 반환타입은 고려 사항이 아님
< 데이터 클래스 >
// 6. 조건문이 존재하는 printInfo 메서드 생성
private void printInfo(boolean isPrint) {
if (isPrint) {
System.out.printf("나의 키 %.1f cm", this.getheight());
System.out.printf("\n나의 몸무게 %.1f kg", this.getweight());
System.out.printf("\n나의 성별 %c", this.getgender());
}
}
// 7. 필수 데이터 출력 및 기본 데이터 선택적 출력
void printInfo() {
// 필수 항목 출력
System.out.printf("\n나의 이름 %s ", this.getname());
System.out.printf("\n나의 전화번호 %s ", this.getphone());
// 선택 항목 출력
printInfo(true);
System.out.println("\n입니다.");
}
}
❻ 기본 데이터를 출력하는 메서드 : 접근 제어자 private으로 지정 → 외부에서 접근 제한됨
논리형 매개변수를 통해 true일 때만 출력되게 설정
❼ 필수 데이터는 항상 출력하고, 기본데이터는 true일 때만 출력되는 메서드 생성
< 실행 클래스 >
// 2. 필수 필드용 생성자 호출
Me me = new Me("홍길동", "010-1234-5678");
me.printInfo();
< 출력 결과 >
isPrint == true 일때
나의 이름 홍길동
나의 전화번호 010-1234-5678
나의 키 150.0 cm
나의 몸무게 50.0 kg
나의 성별 여
입니다.
isPrint == false 일때
나의 이름 홍길동
나의 전화번호 010-1234-5678
입니다.
▶ 모든 필드를 포함하는 생성자 만든 후, 데이터 변경하고 출력하기
< 데이터 클래스 >
// 8. 모든 필드용 생성자
Me(String name, String phone, double height, double weight, char gender){
this.name = name;
this.phone = phone;
this.height = height;
this.weight = weight;
this.gender = gender;
}
< 실행 데이터 >
// 3. 모든 필드용 생성자 호출
me = new Me("백두산", "010-9876-5432", 190, 70, '남');
me.printInfo();
< 출력 결과 >
isPrint == true 일때
나의 이름 백두산
나의 전화번호 010-9876-5432
나의 키 190.0 cm
나의 몸무게 70.0 kg
나의 성별 남
입니다.
isPrint == false 일때
나의 이름 백두산
나의 전화번호 010-9876-5432
입니다.
▷ 세번째 예시
< 데이터 클래스 >
package book;
public class Book {
// 1. 필드 선언 : 접근제어자 private 이용
private String title;
private String author;
private int price;
// 2. 사용자 정의 생성자
public Book(String title, String author, int price) {
this.title = title;
this.author = author;
this.price = price;
}
// 4-1. 명시적으로 객체를 생성하고, 비어있음이란 뜻으로 해석하려는 목적
// -> 나중에 데이터 내용을 설정 가능
public Book() {
this.title = ""; // 타이틀 없음
this.author = ""; // 저자 없음
this.price = 0; // 가격 없음
}
public String getTitle() {
return title;
}
// 책 제목 한번 정해지면 변경 불가하니까 주석 처리 -> book. 했을 때 안뜸
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
// 책 저자는 변경 불가하니까 주석 처리
public void setAuthor(String author) {
this.author = author;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
1. 필드 선언 : 접근제어자로 private 지정 → 같은 클래스 내에서만 접근 가능
2. 사용자 정의 생성자 생성 → 외부에서 생성자를 통해 데이터 값 변경 가
< 실행 클래스 >
package book;
public class BookApp {
public static void main(String[] args) {
// book1, book2 = 로컬변수
// 2. 객체 생성
Book book1 = new Book("이것이 자바다","신용권",35000);
// 2-1. 외부에서 멤버변수에 직접 접근해서 초기화
// book1.title = "이것이 자바다";
// book1.author = "신용권";
// book1.price = 35000;
// -> 4. 접근제어자 : private 사용했으므로 직접 접근 안됨
'백엔드 > JAVA' 카테고리의 다른 글
MVC 패턴 개념 (0) | 2023.05.11 |
---|---|
객체 지향 프로그래밍 이론(3) 및 주사위 게임 예제 실습 (0) | 2023.05.09 |
콘솔창에 메뉴 만들기 예제 실습 및 이론 (0) | 2023.05.04 |
객체 지향 프로그래밍 이론(1) (0) | 2023.05.03 |
가위, 바위, 보 게임 구현하기 예제 실습 (0) | 2023.05.02 |