코드는 혼자 작성할 수도 있지만 현업에서는 여러 명이서 같이 일을 합니다. 여러 명이서 일을 할 때 코드 작성자의 의도를 파악해야 하는 경우가 있는데요. 접근 제어 지시자를 통해 자신이 만든 코드를 캡슐화할 수 있습니다.
접근 제어 지시자를 이용하여 클래스, 변수, 메서드의 접근을 가능하게 하거나 하지 못하도록 할 수 있습니다.
접근 - 클래스, 변수, 메서드의 접근을
제어 - 제어 할 수 있는
지시자 - 키워드
그렇다면 왜 클래스, 생성자, 변수, 메서드를 접근 가능하게 하거나 하지 못하도록 해야 할까요? 이 부분은 깊고 깊은 소프트웨어 설계 관점에서 생겼습니다.
ㅤ
캡슐 안에 들어간 내용물을 보호하고 숨기기 위해서(정보은닉) 내부에서 사용하는 클래스를 노출하지 않거나 클래스 내부에서만 사용하는 메서드가 외부에 노출되지 않도록 숨기고 변수에 저장된 값이 외부에서 변하지 않도록 보호하기 위함입니다.
ㅤ
private
지시자는 생성자, 변수, 메서드에 선언할 수 있고, 기능은 클래스 내부에서만 접근할 수 있도록 합니다.
class Person {
private String name;
Person(String name) {
this.name = name;
}
private void think() {
System.out.printf("%s는 생각한다\n", name);
}
void eat() {
think();
System.out.println("그리고 밥을 먹는다");
}
}
private String name
변수는 클래스 내부에서만 접근할 수 있습니다.
private void think()
메서드는 클래스 내부에서만 접근할 수 있습니다.
Person person = new Person(“록카”);
person.name = “roka”; // name 변수에 접근할 수 없다.
person.think(); // 호출 할 수 없다.
ㅤ
default
는 접근 제어 지시자를 선언하지 않은 순수한 클래스, 생성자, 변수, 메서드를 말하며, default
는 클래스는 같은 패키지 내에서만 import
가 가능하고 생성자도 같은 패키지 내에서만 생성자를 통해 인스턴스를 생성할 수 있습니다.
그리고 변수, 메서드도 같은 패키지 내에서만 접근이 가능합니다.
ㅤ
public
지시자는 클래스, 생성자, 변수, 메서드에 선언할 수 있고 모든 곳에서 접근 가능한 가장 열려있는 접근제어 지시자입니다.
public class Person {
public String name;
public Person(String name) {
this.name = name;
}
public void think() {
System.out.printf("%s는 생각한다\n", name);
}
public void eat() {
think();
System.out.println("그리고 밥을 먹는다");
}
}
public
지시자를 사용한다는 것은 누구나 사용해도 상관없을 만큼 안정화된 클래스, 생성자, 변수, 메서드에 선언합니다. public
지시자를 이용하는 것은 가급적 최소한으로 선언하는 것이 좋습니다.
이유는 현업에서는 여러 명이 하나의 프로젝트를 만들고 고쳐나가기 때문에 각각 범위를 정해서 코드를 작성하게 됩니다.
예시로, A라는 엔지니어가 Person 클래스를 만들고 B라는 엔지니어가 Job이라는 클래스를 만든다고 할 때
Person클래스와 Job클래스는 의존관계가 될 수도 있습니다.
B라는 엔지니어가 사용하지 말아야 할 Person 클래스의 변수나 메서드를 임의로 사용하는 경우가 발생하여 의도하지 않은 방향으로 갈 수 있습니다.
사이드 이펙트도 발생할 수 있습니다. (아직은 이해가 안 되실 겁니다)
ㅤ
protected
지시자는 이후의 강의에서 배웁니다.
ㅤ
접근 지시자 | 설명 | 사용할 수 있는 곳 |
---|---|---|
public | 모든 곳에서 접근 가능합니다. inner 클래스에서도 접근 가능 | 클래스, 생성자, 변수, 메서드 |
protected | 일반적으론 같은 패키지가 아닌 다른 패키지 내에서 접근 불가합니다. 다만 다른 패키지라고 하더라도 상속으로는 접근 가능합니다. | 생성자, 변수, 메서드 |
default | 같은 패키지가 아닌 다른 패키지 내에서 접근 불가합니다. | 클래스, 생성자, 변수, 메서드 |
private | 클래스 내부에서만 접근 가능합니다. | inner 클래스, 생성자, 변수, 메서드 |
ㅤ
실습 코드에 이미 코드가 작성되어 있습니다.
하나씩 주석을 풀어 실행해봅시다.
ㅤ
코드 작성(Main.java)
codelatte.defaultpkg.Coffee coffee = new codelatte.defaultpkg.Coffee("Coffee");
출력
codelatte/Main.java:9: error: Coffee is not public in codelatte.defaultpkg; cannot be accessed from outside package codelatte.defaultpkg.Coffee coffee = new codelatte.defaultpkg.Coffee("Coffee");
생성자가 default로 선언되어 있기 때문에 다른 패키지에 속해있는 Main.java에서는 Coffee 생성자를 선언할 수 없습니다.
ㅤ
코드 변경(Main.java)
codelatte.privatepkg.Coffee coffee = new codelatte.privatepkg.Coffee(“Coffee");
System.out.println(coffee.name);
출력
codelatte/Main.java:15: error: name has private access in Coffee System.out.println(coffee.name); 1 error
privatepkg의 Coffee의 name 변수는 private 접근 제어 지시자가 선언되어 있으므로 직접 접근할 수 없습니다.
ㅤ
코드 변경(Main.java)
codelatte.publicpkg.Coffee coffee = new codelatte.publicpkg.Coffee(“Coffee");
System.out.println(coffee.name);
출력
Coffee
publicpkg의 Coffee의 name 변수는 public 접근 제어 지시자가 선언되어 있으므로 직접 접근할 수 있습니다.
4:39 public 지시자 설명에서 질문입니다. person.eat(); eat() 자체는 public 지시자가 앞에 있어서 호출이 가능한 것은 이해가 됩니다. 다만 궁금한 것은 eat()를 호출하게 되면 think()를 호출하게 됩니다. 그런데, think()는 default 접근 제어 지시자가 있는 거라 과연 패키지가 다른 Main.java에서 think() 메세드를 호출이 가능한지 의문이 들었습니다. 또다시 곰곰이 생각해보니 eat() 메서드는 클래스 내부의 think()를 호출하기 때문에 외부에서의 접근이 아니므로 가능하게 되는 건가요??? (올바르게 생각했는지 검토 부탁드립니다) 그렇다면 person.think(); 를 하게되면 호출이 안 되지 않나요? 끝까지 읽어주셔서 감사드립니다.
안녕하세요. 코드라떼입니다 :) 말씀하신대로 eat() 메서드에서 think() 메서드 호출은 외부에서 호출하는 것이 아니므로 상관없습니다. 그리고 외부에서 person.think() 메서드를 호출할 수는 없습니다. 외부에서 eat() 메서드를 호출하고 eat() 메서드가 think() 메서드를 호출한다면, 어떻게 생각해보면 결론적으로 외부의 호출로 인해 think() 메서드가 호출되는 것이 아닌가 헷갈릴 수 있지만 단순히 외부에서 명시적으로 호출되는 메서드에 대한 접근 가능 여부만 판단합니다. 감사합니다 :)
혹시 제가 임의로 package를 만들고 그 안에 java 파일을 만들고 컴파일을 하려고 하는데, 가장 처음 컴파일 했던 Main.java이 계속 컴파일이 됩니다. 임의로 컴파일 할 파일을 변경할 수 있을까요?
안녕하세요. 코드라떼입니다 :) 어떤 방식으로 컴파일을 했는지에 따라 달라집니다. 에디터라면, 에디터에서 'Run' 버튼을 클릭하여 실행하면 일반적인 상황에선 프로젝트내에 있는 전체 파일을 컴파일 후 컴파일된 파일을 '자바 가상 머신'이 읽어서 실행됩니다. 좀 더 자세한 상황과 프로젝트 구조를 파악하기 위해 '도전하기'후 제공되는 오픈 채팅방에서 질문을 주시면 감사하겠습니다. 오픈 채팅방에서 스크린샷을 제공하여 질문하시면 좀 더 상세히 답변드릴 수 있습니다. 감사합니다.
각 패키지에 있는 Coffee 클래스의 접근 제어 지시자들을 확인해보세요. Main.java에 있는 것을 주석을 하나씩 풀어봅시다.
코드는 혼자 작성할 수도 있지만 현업에서는 여러 명이서 같이 일을 합니다. 여러 명이서 일을 할 때 코드 작성자의 의도를 파악해야 하는 경우가 있는데요. 접근 제어 지시자를 통해 자신이 만든 코드를 캡슐화할 수 있습니다.
접근 제어 지시자를 이용하여 클래스, 변수, 메서드의 접근을 가능하게 하거나 하지 못하도록 할 수 있습니다.
접근 - 클래스, 변수, 메서드의 접근을
제어 - 제어 할 수 있는
지시자 - 키워드
그렇다면 왜 클래스, 생성자, 변수, 메서드를 접근 가능하게 하거나 하지 못하도록 해야 할까요? 이 부분은 깊고 깊은 소프트웨어 설계 관점에서 생겼습니다.
ㅤ
캡슐 안에 들어간 내용물을 보호하고 숨기기 위해서(정보은닉) 내부에서 사용하는 클래스를 노출하지 않거나 클래스 내부에서만 사용하는 메서드가 외부에 노출되지 않도록 숨기고 변수에 저장된 값이 외부에서 변하지 않도록 보호하기 위함입니다.
ㅤ
private
지시자는 생성자, 변수, 메서드에 선언할 수 있고, 기능은 클래스 내부에서만 접근할 수 있도록 합니다.
class Person {
private String name;
Person(String name) {
this.name = name;
}
private void think() {
System.out.printf("%s는 생각한다\n", name);
}
void eat() {
think();
System.out.println("그리고 밥을 먹는다");
}
}
private String name
변수는 클래스 내부에서만 접근할 수 있습니다.
private void think()
메서드는 클래스 내부에서만 접근할 수 있습니다.
Person person = new Person(“록카”);
person.name = “roka”; // name 변수에 접근할 수 없다.
person.think(); // 호출 할 수 없다.
ㅤ
default
는 접근 제어 지시자를 선언하지 않은 순수한 클래스, 생성자, 변수, 메서드를 말하며, default
는 클래스는 같은 패키지 내에서만 import
가 가능하고 생성자도 같은 패키지 내에서만 생성자를 통해 인스턴스를 생성할 수 있습니다.
그리고 변수, 메서드도 같은 패키지 내에서만 접근이 가능합니다.
ㅤ
public
지시자는 클래스, 생성자, 변수, 메서드에 선언할 수 있고 모든 곳에서 접근 가능한 가장 열려있는 접근제어 지시자입니다.
public class Person {
public String name;
public Person(String name) {
this.name = name;
}
public void think() {
System.out.printf("%s는 생각한다\n", name);
}
public void eat() {
think();
System.out.println("그리고 밥을 먹는다");
}
}
public
지시자를 사용한다는 것은 누구나 사용해도 상관없을 만큼 안정화된 클래스, 생성자, 변수, 메서드에 선언합니다. public
지시자를 이용하는 것은 가급적 최소한으로 선언하는 것이 좋습니다.
이유는 현업에서는 여러 명이 하나의 프로젝트를 만들고 고쳐나가기 때문에 각각 범위를 정해서 코드를 작성하게 됩니다.
예시로, A라는 엔지니어가 Person 클래스를 만들고 B라는 엔지니어가 Job이라는 클래스를 만든다고 할 때
Person클래스와 Job클래스는 의존관계가 될 수도 있습니다.
B라는 엔지니어가 사용하지 말아야 할 Person 클래스의 변수나 메서드를 임의로 사용하는 경우가 발생하여 의도하지 않은 방향으로 갈 수 있습니다.
사이드 이펙트도 발생할 수 있습니다. (아직은 이해가 안 되실 겁니다)
ㅤ
protected
지시자는 이후의 강의에서 배웁니다.
ㅤ
접근 지시자 | 설명 | 사용할 수 있는 곳 |
---|---|---|
public | 모든 곳에서 접근 가능합니다. inner 클래스에서도 접근 가능 | 클래스, 생성자, 변수, 메서드 |
protected | 일반적으론 같은 패키지가 아닌 다른 패키지 내에서 접근 불가합니다. 다만 다른 패키지라고 하더라도 상속으로는 접근 가능합니다. | 생성자, 변수, 메서드 |
default | 같은 패키지가 아닌 다른 패키지 내에서 접근 불가합니다. | 클래스, 생성자, 변수, 메서드 |
private | 클래스 내부에서만 접근 가능합니다. | inner 클래스, 생성자, 변수, 메서드 |
ㅤ
실습 코드에 이미 코드가 작성되어 있습니다.
하나씩 주석을 풀어 실행해봅시다.
ㅤ
코드 작성(Main.java)
codelatte.defaultpkg.Coffee coffee = new codelatte.defaultpkg.Coffee("Coffee");
출력
codelatte/Main.java:9: error: Coffee is not public in codelatte.defaultpkg; cannot be accessed from outside package codelatte.defaultpkg.Coffee coffee = new codelatte.defaultpkg.Coffee("Coffee");
생성자가 default로 선언되어 있기 때문에 다른 패키지에 속해있는 Main.java에서는 Coffee 생성자를 선언할 수 없습니다.
ㅤ
코드 변경(Main.java)
codelatte.privatepkg.Coffee coffee = new codelatte.privatepkg.Coffee(“Coffee");
System.out.println(coffee.name);
출력
codelatte/Main.java:15: error: name has private access in Coffee System.out.println(coffee.name); 1 error
privatepkg의 Coffee의 name 변수는 private 접근 제어 지시자가 선언되어 있으므로 직접 접근할 수 없습니다.
ㅤ
코드 변경(Main.java)
codelatte.publicpkg.Coffee coffee = new codelatte.publicpkg.Coffee(“Coffee");
System.out.println(coffee.name);
출력
Coffee
publicpkg의 Coffee의 name 변수는 public 접근 제어 지시자가 선언되어 있으므로 직접 접근할 수 있습니다.
4:39 public 지시자 설명에서 질문입니다. person.eat(); eat() 자체는 public 지시자가 앞에 있어서 호출이 가능한 것은 이해가 됩니다. 다만 궁금한 것은 eat()를 호출하게 되면 think()를 호출하게 됩니다. 그런데, think()는 default 접근 제어 지시자가 있는 거라 과연 패키지가 다른 Main.java에서 think() 메세드를 호출이 가능한지 의문이 들었습니다. 또다시 곰곰이 생각해보니 eat() 메서드는 클래스 내부의 think()를 호출하기 때문에 외부에서의 접근이 아니므로 가능하게 되는 건가요??? (올바르게 생각했는지 검토 부탁드립니다) 그렇다면 person.think(); 를 하게되면 호출이 안 되지 않나요? 끝까지 읽어주셔서 감사드립니다.
안녕하세요. 코드라떼입니다 :) 말씀하신대로 eat() 메서드에서 think() 메서드 호출은 외부에서 호출하는 것이 아니므로 상관없습니다. 그리고 외부에서 person.think() 메서드를 호출할 수는 없습니다. 외부에서 eat() 메서드를 호출하고 eat() 메서드가 think() 메서드를 호출한다면, 어떻게 생각해보면 결론적으로 외부의 호출로 인해 think() 메서드가 호출되는 것이 아닌가 헷갈릴 수 있지만 단순히 외부에서 명시적으로 호출되는 메서드에 대한 접근 가능 여부만 판단합니다. 감사합니다 :)
혹시 제가 임의로 package를 만들고 그 안에 java 파일을 만들고 컴파일을 하려고 하는데, 가장 처음 컴파일 했던 Main.java이 계속 컴파일이 됩니다. 임의로 컴파일 할 파일을 변경할 수 있을까요?
안녕하세요. 코드라떼입니다 :) 어떤 방식으로 컴파일을 했는지에 따라 달라집니다. 에디터라면, 에디터에서 'Run' 버튼을 클릭하여 실행하면 일반적인 상황에선 프로젝트내에 있는 전체 파일을 컴파일 후 컴파일된 파일을 '자바 가상 머신'이 읽어서 실행됩니다. 좀 더 자세한 상황과 프로젝트 구조를 파악하기 위해 '도전하기'후 제공되는 오픈 채팅방에서 질문을 주시면 감사하겠습니다. 오픈 채팅방에서 스크린샷을 제공하여 질문하시면 좀 더 상세히 답변드릴 수 있습니다. 감사합니다.
각 패키지에 있는 Coffee 클래스의 접근 제어 지시자들을 확인해보세요. Main.java에 있는 것을 주석을 하나씩 풀어봅시다.