private < default(nothing) < protected < public
private
- 같은 클래스 내에서만 접근 가능
default(nothing)
- 같은 패키지 내에서만 접근 가능
protected
- 같은 패키지 내에 있거나, 다른 패키지의 자식 클래스에서 접근 가능
public
- 접근 제한 없음
new -> package -> ModifierTest class 생성
∴ 같은 클래스 내에 있는 public에서 접근 가능
package pkg;
public class ModifierTest {
private void messageInside() {
System.out.println("This is private modifier");
}
public void messageOutside() {
System.out.println("This is public modifier");
messageInside(); // private은 같은 클래스 안에서 접근 하능하다고 하였으니 OK
}
protected void messageProtected() {
System.out.println("This is protected modifier");
}
void messagePackagePrivate() {
System.out.println("This is package private modifier");
}
}
import pkg.ModifierTest;
class Child extends ModifierTest { // 같은 패키지 안 아무것도 없는 자바 밑에 있는 것이기 때문에 호출
void callParentProtected() { // 아무것도 안붙었기 때문에 package private
System.out.println("Call my parent's protected method");
super.messageProtected();
// super() : 내가 상속 받은 부모 클래스 가르키는 키워드
// protected는 같은 패키지 내 또는 다른 패키지 자식 클래스에서 접근 가능하다 하였으니 OK
}
}
public class Main { // 같은 패키지 안 아무것도 없는 자바 밑에 있는 것이기 때문에 호출
public static void main(String[] args) {
ModifierTest modifierTest = new ModifierTest();
modifierTest.messageOutside();
// modifierTest.messageInside();
// compile error
// modifierTest.messageProtected();
// compile error
// modifierTest.messagePackagePrivate();
// public이 아니라 패키지 바깥에서 access할 수 없음
Child child = new Child();
child.callParentProtected();
}
}
패키지를 만들고 그 안에 새로운 클래스를 만들게 되면 맨 위 package 선언부가 추가됨
:: 접근제어자 사용하는 이유
- 객체지향프로그래밍이란
- 객체들 간 상호작용을 코드로 표현하는 것
- 객체간의 관계에 따라 접근 가능한 것과 아닌것의 구분이 필요
- 클래스 내부에 선언된 데이터의 부적절한 사용으로부터 보호하기 위해
- 이것을 캡슐화라고함
접근제어자는 캡슐화가 가능할 수 있도록 접는 도구이다.
예제
x : 가로 | y : 세로 | z : 높이
- abstract class Bird 내용 채우고, 날 수 없는 새가 있을 때도 if문으로 설정
- 날 수 있더라도 멕시멈 몇미터까지인지 return받고, 날 수 없을 경우에는 false를 return받음
- 아래 main class에 찍어보기
abstract class Bird { private int x, y, z; void fly(int x, int y, int z) { printLocation(); System.out.println("이동합니다."); this.x = x; this.y = y; if (flyable(z)) { // 만약 날 수 있다면 z로 이동 this.z = z; } else { // 날 수 없다면 System.out.println("그 높이로는 날 수 없습니다"); } printLocation(); } abstract boolean flyable(int z); // 날 수 있는 새 날 수 없는 새 판단하는 추상 메소드 // flyable은 구현제가 없는데도 abstract class 안에 있는 여기서 진짜 함수처럼 사용됨 // 내용은 자식클래스에서 구현 public void printLocation() { System.out.println("현재 위치 (" + x + ", " + y + ", " + z + ")"); } } class Pigeon extends Bird { // alt + enter치고 맨위 추천 누르면 아래 오버라이드 생성됨 @Override boolean flyable(int z) { return z < 10000; // 높이 10000m 이하까지만 날 수 있도록 return } } // flyable 구현 class Peacock extends Bird { @Override boolean flyable(int z) { return false; // 공작새는 날 수 없으니 항상 false return } } // flyable 구현 public class Main { public static void main(String[] args) { Bird pigeon = new Pigeon(); Bird peacock = new Peacock(); System.out.println("-- 비둘기 --"); pigeon.fly(1, 1, 3); System.out.println("-- 공작새 --"); peacock.fly(1, 1, 3); System.out.println("-- 비둘기 --"); pigeon.fly(3, 3, 30000); } } // -- 비둘기 -- // 현재 위치 (0, 0, 0) // 이동합니다. // 현재 위치 (1, 1, 3) // -- 공작새 -- // 현재 위치 (0, 0, 0) // 이동합니다. // 그 높이로는 날 수 없습니다 // 현재 위치 (1, 1, 0) // -- 비둘기 -- // 현재 위치 (1, 1, 3) // 이동합니다. // 그 높이로는 날 수 없습니다 // 현재 위치 (3, 3, 3)
- fly(x, y, z) 함수는 Bird 를 상속받는 모든 클래스에서 동일한 동작
- flyable은 구현체가 없는데도 abstract class 안에 있는 여기서 진짜 함수처럼 사용됨
- 내용은 자식클래스에서 구현
- 공작새는 날 수 없으니 항상 false 리턴
- x, y 좌표로만 움직임
- 비둘기는 기준이 되는 일정 높이가 되기 전까지는 날 수 있으므로 z좌표 움직임
- 새의 종류마다 중복코드 없이 구현하려면 추상클래스와 추상메소드를 이용해서 구현 가능
- 중복코드 제거
- 각 새마다 주어진 위치까지 날 쑤 있는지 판단 할 수 잇는 유연성 허용
parameter를 받고 싶다면 추상메소드 옆 괄호 안에 넣고 body ( { } )는 없이 하면 됨
interface 인터페이스명{ public abstract void 추상메소드명(); } interface MyInterface { void myMethod(int x) }
예제
- 인터페이스는 멤버를 가지지 못하고 동작 즉 메소드만 정의
- 실제 구현은 implement 키워드 통해서 구현
interface Flyable { void fly(int x, int y, int z); } class Pigeon implements Flyable{ private int x,y,z; // 인터페이스는 필드가 없기 때문에 여기에 정해줌 @Override public void fly(int x, int y, int z) { printLocation(); System.out.println("날아갑니다."); this.x = x; this.y = y; this.z = z; printLocation(); } public void printLocation() { System.out.println("현재 위치 (" + x + ", " + y + ", " + z + ")"); } } public class Main { public static void main(String[] args) { Flyable bird = new Pigeon(); bird.fly(1, 2, 3); // bird.printLocation(); // compile error } }
- 인터페이스는 필드가 없기 때문에 implements 키워드로 구현한 Flyable 아래 private로 정해줌
class Pigeon implements Flyable{ private int x,y,z; }
- bird.printLocation();
- error
- Flyable 타입으로 선언한 bird 변수는 실제로 Pigeon 객체이지만
- interface인 Flyable 에 선언되지 않은 printLocation() 이라는 함수 호출할 수 없음
interface type 으로 선언되어있는 부분에서는 실제 객체가 무엇이든지, interface에 정의된 행동만 할 수 있음
요구조건 만족하는 클래스 작성
요구사항 1. 사람은 자식, 부모님, 조부모님이 있다. 2. 모든 사람은 이름, 나이, 현재 장소정보(x,y좌표)가 있다. 3. 모든 사람은 걸을 수 있다. 장소(x, y좌표)로 이동한다. 4. 자식과 부모님은 뛸 수 있다. 장소(x, y좌표)로 이동한다. 5. 조부모님의 기본속도는 1이다. 부모의 기본속도는 3, 자식의 기본속도는 5이다. 6. 뛸때는 속도가 기본속도대비 +2 빠르다. 7. 수영할때는 속도가 기본속도대비 +1 빠르다. 8. 자식만 수영을 할 수 있다. 장소(x, y좌표)로 이동한다.
요구조건 만족하는 클래스 바탕으로 Main함수로 동작 출력
1. 모든 종류의 사람의 인스턴스는 1개씩 생성한다. 2. 모든 사람의 처음 위치는 x,y 좌표가 (0,0)이다. 3. 모든 사람의 이름, 나이, 속도, 현재위치를 확인한다. 4. 걸을 수 있는 모든 사람이 (1, 1) 위치로 걷는다. 5. 뛸 수 있는 모든 사람은 (2,2) 위치로 뛰어간다. 6. 수영할 수 있는 모든 사람은 (3, -1)위치로 수영해서 간다.
public class Human {
String name;
int age;
int speed;
int x, y;
public Human(String name, int age, int speed, int x, int y) { // 초기화 생성자
this.name = name;
this.age = age;
this.speed = speed;
this.x = x;
this.y = y;
}
public Human(String name, int age, int speed) { // 위 생성자 이용
this(name, age, speed, 0, 0);
}
public String getLocation() {
return "(" + x + ", " + y + ")";
}
protected void printWhoAmI() {
System.out.println("My name is " + name + ". " + age + " aged.");
}
}
public interface Walkable {
void walk(int x, int y);
}
public interface Runable {
void run (int x, int y);
}
public interface Swimmable {
void swim(int x, int y);
}
public class GrandParent extends Human implements Walkable {
public GrandParent(String name, int age) { // 생성자
super(name, age, 1);
}
@Override // 인터페이스 구현
public void walk(int x, int y) {
printWhoAmI();
System.out.println("walk speed: " + speed);
this.x = x;
this.y = y;
System.out.println("Walked to " + getLocation());
}
}
public class Parent extends Human implements Walkable, Runable{
public Parent(String name, int age) {
super(name, age, 3);
}
@Override
public void run(int x, int y) {
printWhoAmI();
System.out.println("run speed: " + (speed + 2));
this.x = x;
this.y = y;
System.out.println("ran to " + getLocation());
}
@Override
public void walk(int x, int y) {
printWhoAmI();
System.out.println("walk speed: " + speed);
this.x = x;
this.y = y;
System.out.println("Walked to " + getLocation());
}
}
public class Child extends Human implements Walkable, Runable, Swimmable{
public Child(String name, int age) {
super(name, age, 5);
}
@Override
public void run(int x, int y) {
printWhoAmI();
System.out.println("run speed: " + (speed + 2));
this.x = x;
this.y = y;
System.out.println("ran to " + getLocation());
}
@Override
public void swim(int x, int y) {
printWhoAmI();
System.out.println("swim speed: " + (speed + 1));
this.x = x;
this.y = y;
System.out.println("swum to " + getLocation());
}
@Override
public void walk(int x, int y) {
printWhoAmI();
System.out.println("walk speed: " + speed);
this.x = x;
this.y = y;
System.out.println("Walked to " + getLocation());
}
}
public class Main {
public static void main(String[] args) {
Human grandParent = new GrandParent("할아버지", 80);
Human parent = new Parent("엄마", 52);
Human child = new Child("나", 20);
Human[] humans = {grandParent, parent, child};
for (Human human : humans) {
System.out.println(human.name + ", 나이: " + human.age + ", 속도: " + human.speed + ", 장소: " + human
.getLocation());
}
System.out.println("<활동 시작>");
for (Human human : humans) {
if (human instanceof Walkable){
((Walkable) human).walk(1,1); // human.walk 치고 엔터치면 자동완선
// 위에선 Human type인데 if 문에서 Walkable인게 확인됐으니 Walkable type으로 캐스팅 하겠다라는 의미
System.out.println("- - - - - -");
}
if (human instanceof Runable){
((Runable) human).run(2,2);
System.out.println("- - - - - -");
}
if (human instanceof Swimmable){
((Swimmable) human).swim(3,-1);
System.out.println("- - - - - -");
}
}
}
}
할아버지, 나이: 80, 속도: 1, 장소: (0, 0)
엄마, 나이: 52, 속도: 3, 장소: (0, 0)
나, 나이: 20, 속도: 5, 장소: (0, 0)
<활동 시작>
My name is 할아버지. 80 aged.
walk speed: 1
Walked to (1, 1)
- - - - - -
My name is 엄마. 52 aged.
walk speed: 3
Walked to (1, 1)
- - - - - -
My name is 엄마. 52 aged.
run speed: 5
ran to (2, 2)
- - - - - -
My name is 나. 20 aged.
walk speed: 5
Walked to (1, 1)
- - - - - -
My name is 나. 20 aged.
run speed: 7
ran to (2, 2)
- - - - - -
My name is 나. 20 aged.
swim speed: 6
swum to (3, -1)
- - - - - -
캐스팅이란?
실제 객체가 Walkable 이기도 하고 Human이기도 했을 때,
어떤 종류의 type으로 그것인 척해서 사용하겠다라는 의미노트에 손으로 적어보면서 확인하고 익히기!!!! 젭r