2022. 10. 5. 15:04ㆍDev.Program/Java & Spring
p.276
======== JAVA0318 - Ex.java 만들기
p.276
< 인터페이스(interface) >
- 클래스가 아니므로 선언 시 class 키워드 대신 interface 키워드 사용
- 인터페이스는 추상메서드, 상수만 가질 수 있다.
- ⇒ 모든 메서드는 public abstract 가 붙은 추상메서드로 취급됨(생략 가능)
- ⇒ 모든 멤버변수는 public static final 이 붙인 상수로 취급됨(생략 가능)
- 추상클래스와 마찬가지로 객체 생성이 불가능
- ⇒ 단, 참조변수 타입으로는 사용 가능 = 다형성 활용(업캐스팅) 가능
- 추상메서드 구현을 강제하여, 코드의 통일성이 향상됨
- 클래스에서 인터페이스를 상속받아 구현해야할 경우 implements 키워드 사용
- 인터페이스끼리 상속받을 경우 extends 키워드 사용
======== 동물.java → Interface로 만들어보기
- class 파일 만드는 것보다 간단하다!
- abstract 가 없어도 추상메서드로 취급하기 때문에 {} 를 넣으면 오류남!
- public도 생략가능!
- 모두 abstract기 때문에 abstract를 안적어도 전부 추상메서드이다.
- public abstract 생략가능
- 최종 : class 파일이랑 다르게 main() 메서드도 없고 코드가 엄청 간단하다
<Ex.java>
- 방금 만든 interface 상속 받음!
- 오류!
- 오류창 확인 : 고래의 메서드도 추상메서드라 구현부(body)를 가질 수 없다.
- public void 번식(); 으로 적는 건 가능!
- 오류! extends 를 사용했기 때문!
- 클래스에서 인터페이스를 상속받아 구현해야할 경우 implements 키워드 사용
- im 까지만 쓰고 Ctrl + space(자동완성) 누르면 자동으로 완성됨!
- Ctrl + space 눌러보면 내가 상속(구현)받을 수 있는 인터페이스들이 보임.
- 인터페이스는 다중 상속이 가능하다!
- 근데 오류가 뜸! 왜?
- 오류창 확인 : 상속받은 추상메서드를 구현하지 않았기 때문
- 인터페이스를 상속(구현)할 때, 2개 이상의 부모로부터 상속(구현)이 가능하다.
- ⇒ 즉, 인터페이스는 다중 구현을 지원함
p.278-279 인터페이스
<Ex.java>
- 인터페이스 내의 메서드는 전부 추상메서드
- public abstract 가 생략된 추상메서드기 때문에 바디{}를 가질 수 없음(오류!)
- 인터페이스도 객체 생성이 불가하다.
- extends 키워드를 사용하면 상속 받을 MyInterface가 안보임.
- implements 키워드로 상속(구현) 받음! - MyInterface 보임.
- 서브클래스에서 구현한 메서드 앞에 public을 지울 경우 오류
- public 보다 좁은 protected를 적어도 오류!
- 부모의 메서드 접근제한자보다 좁을 수 없으므로(같거나 넓어야함) 반드시 public 사용
- public 을 사용하면 오류 다 사라짐.
Flyer 인터페이스 정의
⇒ 이륙(takeoff()), 비행(fly()), 착륙(land()) 메서드 정의 = 추상메서드
SuperMan 클래스 정의 ⇒ Flyer 인터페이스를 상속받아 구현
⇒ 각 메서드 구현하여 "SuperMan 이륙", "SuperMan 비행", "SuperMan 착륙" 출력
Airplane 클래스 정의 ⇒ Flyer 인터페이스를 상속받아 구현
⇒ 각 메서드 구현하여 "Airplane 이륙", "Airplane 비행", "Airplane 착륙" 출력
# tip. interface MyInterface {} 내의 상수 (앞에서 놓친 부분!)
- 상수는 원래 대문자로 쓰기로 함(약속)
- 좀 더 좋은 코드를 가지기 위해선 num1, num2 대문자로 바꿔주는 게 좋다!
<Ex.java → main()메서드 부분>
- 인스턴스 생성
- 인터페이스의 인스턴스 생성은 불가능
- 하지만, 참조변수 타입으로 다형성 활용 가능
- 출력창
======== Ex2.java 만들기
<Ex2.java>
- IHello, IGoodbye 인터페이스를 상속받는 ITotal 인터페이스 정의
- ⇒ 인터페이스 끼리는 다중 상속이 가능하며, extends 키워드를 사용하여 상속
- Alt + Shift + S + V 눌러보면 구현해야 할 메서드가 총 3개 (체크된 부분 확인 가능)
- 필수로 구현해야하기 때문에 전부 체크 되어있음
- 필수로 구현해야할 추상메서드 3개 구현
- 이렇게 추상메서드 하나라도 구현하지 않으면 오류!
- 추상 메서드를 구현하지 않아도 오류를 없애는 방법은??
- ⇒ abstract(추상) 클래스로 정의하면 추상메서드를 구현하지 않아도 오류가 사라짐!
- (대신 이 클래스도 인스턴스 생성은 못함 자식클래스 중 누군가는 상속 받아서 추상메서드를 구현해줘야 인스턴스 생성 후 사용 가능)
======== Ex3.java 만들기
<Ex3.java>
- 이들의 공통 부모는 Object
- 나쁜 예 (코드가 길어짐)
> 서로 상속 관계가 없는 클래스들 간에 인터페이스를 통한 상속관계를 부여하면 다형성을 확장하여 사용할 수 있게 된다.
- 공통 부모인 interface를 만듦
- 공통의 충전 기능에 대한 추상메서드 정의
- 기존 클래스를 상속받은 상태에서 추가적인 상속을 위해 인터페이스를 활용할 수 있다!
- 인스턴스 생성 후 charge() 메서드를 부를 때 코드가 훨씬 간단해짐.
- Chargeable 인터페이스에 공통 추상메서드 charge() 가 존재하므로 별도의 다운캐스팅 없이 바로 charge() 메서드 호출이 가능하다!
- 좋은 예 (코드가 훨씬 간단)
> 향상 for문(확장 for문) 안 배워서 위 코드 중 for문만 우리가 배운대로 바꿈
for(int i = 0; i < objs2.length; i++) {
Chargeable c = objs2[i];
c.charge();
}
~p.292 [p.293 2.6은 나중에 배움]
======== Ex4.java 만들기
<Ex4.java>
- 체력만 생성자 만들기(Alt + Shift + S + O 생성자 단축키)
- (final 부분 최대체력이 오류 난 이유는 상수인데 초기화를 안시켜놨기 때문)
- 최대체력(final 상수)도 여기서 같이 초기화시켜줌 → final 부분 오류 사라짐
# tip. 인터페이스를 만들 땐 ~able(~할수있는)으로 만든다.
- 지금은 한글로 적는다고 interface 공격가능{} 이라 했지만 보통은 interface Movable{} 이런 식으로 인터페이스 명에 ~able을 사용
- 병사에 오류 뜸 : 오류 뜨는 2가지 이유
- 우선 첫 번째로, 유닛 클래스의 이 부분 때문에 오류가 난다 !
- final 상수인 최대체력을 초기화하기 위한 생성자 정의
- 오류창 확인 : final 상수인 최대체력을 초기화하기 위한 생성자를 정의해야함
- 그냥 바로 super() 안에 초기화 시켜줌!
- 두 번째는, 상속받은 추상메서드를 정의하지 않았기 때문! (오류창 확인)
- 오류나는 두 가지 이유를 전부 고친 뒤에는 오류가 사라진다.
> 병사(Marine) 클래스 정의 - 유닛, 공격가능, 이동가능
class 병사 extends 유닛 implements 공격가능, 이동가능 {
public 병사() { // final 상수인 체력을 초기화하기 위한 생성자 정의
super(50); // 유닛 클래스의 생성자를 호출하여 체력 전달
공격력 = 5;
}
@Override
public void 이동(int x, int y) {
System.out.println("걸어서 x, y 좌표로 무브!");
}
@Override
public void 공격(유닛 u) {
System.out.println("총으로 " + u + "를 공격!");
u.체력 -= 공격력; // 공격력만큼 체력 감소
}
public String toString() {
return "병사";
} ⇒ 이부분은 아직 뭔지 모름! (선생님 따라 코드 침)
}
> 탱크 클래스 정의 - 유닛, 공격가능, 이동가능
class 탱크 extends 유닛 implements 공격가능, 이동가능 {
public 탱크() { // final 상수인 체력을 초기화하기 위한 생성자 정의
super(150); // 유닛 클래스의 생성자를 호출하여 체력 전달
공격력 = 30;
}
@Override
public void 이동(int x, int y) {
System.out.println("바퀴를 사용하여 x, y 좌표로 무브!");
}
@Override
public void 공격(유닛 u) {
System.out.println("대포로 " + u + "를 공격!");
u.체력 -= 공격력; // 공격력만큼 체력 감소
}
public String toString() {
return "탱크";
}
}
> 기계일꾼(SCV) 클래스 정의 - 유닛, 공격가능, 이동가능
class 기계일꾼 extends 유닛 implements 공격가능, 이동가능 {
public 기계일꾼() { // final 상수인 체력을 초기화하기 위한 생성자 정의
super(60); // 유닛 클래스의 생성자를 호출하여 체력 전달
공격력 = 2;
}
@Override
public void 이동(int x, int y) {
System.out.println("걸어서 x, y 좌표로 무브!");
}
@Override
public void 공격(유닛 u) {
System.out.println("용접기로 " + u + "를 공격!");
u.체력 -= 공격력; // 공격력만큼 체력 감소
}
public String toString() {
return "기계일꾼";
}
// 기계 유닛을 수리하는 수리() 메서드 정의
public void 수리(유닛 u) { // 공통항목으로 유닛타입 객체를 전달받음
// 대상 유닛의 체력이 최대체력이 될 때까지 체력을 1씩 증가시킴(수리)
while(u.체력 < u.최대체력) {
u.체력++;
System.out.println("수리 중... [" + u.체력
+ "/" + u.최대체력 + "]");
}
System.out.println(u + "의 수리가 끝났습니다!");
}
}
<Ex4.java → main() 메서드>
- 출력창
> 체력이 깎였으니 이제 수리에 들어가보자!
- 출력창
> 근데 문제가 되는점! 기계일꾼이 사람인 병사도 수리(?)해버림
→ 기계일꾼은 기계인 탱크만 수리 가능, 병사는 수리가 아니라 치료를 해야됨
- 출력창
⇒ 이렇게 되면 안된다! 유닛 u.** 으로 받아오기 때문에 병사도 구분없이 수리함.
< 인터페이스 활용법 >
- 수리가 가능한 유닛들을 별도로 구분하기 위한 인터페이스 활용법
- ⇒ 아무 코드도 기술되지 않은 빈 인터페이스를 정의하고 해당클래스에 인터페이스를 구현하도록 하면 마카(Marker) 용도로 활용 가능
- ⇒ 추상메서드가 하나도 없으므로 구현의 강제성이 없이 표시 용도로만 사용
> 해결 방법
- 이렇게 빈 인터페이스 하나 추가!
- 기계 일꾼에서 받아오는 것도 수리가능 타입으로 받아옴
- 전부 수리가능 타입으로 수정해 줌!
class 병사 extends 유닛 implements 공격가능, 이동가능 {}
class 탱크 extends 유닛 implements 공격가능, 이동가능, 수리가능 {}
class 기계일꾼 extends 유닛 implements 공격가능, 이동가능, 수리가능 {}
⇒ 이렇게 만들어 준 수리가능 인터페이스를 탱크와 기계일꾼에게만 적용하면 병사는 더 이상 기계일꾼이 수리하지 못함!
> 이렇게 바꾸면 main() {} 에서
- 오류남 ( 병사는 더이상 수리하지 못하기 때문)
> 병사를 치료해 줄 치료가능 인터페이스를 만들어 줌.
interface 치료가능 {}
// 간호장교 클래스 정의 - 유닛, 공격가능, 이동가능
class 간호장교 extends 유닛 implements 이동가능, 치료가능 {
public 간호장교() { // final 상수인 체력을 초기화하기 위한 생성자 정의
super(60); // 유닛 클래스의 생성자를 호출하여 체력 전달
공격력 = 2;
}
@Override
public void 이동(int x, int y) {
System.out.println("걸어서 x, y 좌표로 무브!");
}
public String toString() {
return "간호장교";
}
// 생체 유닛을 치료하는 치료() 메서드 정의
public void 치료(치료가능 치료유닛) {
if(치료유닛 instanceof 유닛) { // 치료유닛은 유닛타입입니까?
유닛 u = (유닛)치료유닛;
while(u.체력 < u.최대체력) {
u.체력++;
System.out.println("수리 중... [" + u.체력
+ "/" + u.최대체력 + "]");
}
System.out.println(u + "의 치료가 끝났습니다!");
}
}
}
class 병사 extends 유닛 implements 공격가능, 이동가능, 치료가능 {}
- 병사 클래스에 치료가능 인터페이스도 적용
<Ex4.java → main() 메서드>
- 탱크는 수리하고, 병사는 치료한다!
- 출력창
⇒ 이런 식으로 인터페이스를 활용하여 구분할 수 있다!
'Dev.Program > Java & Spring' 카테고리의 다른 글
[Java] 향상된for문 / 어노테이션 (1) | 2022.10.05 |
---|---|
[Java] enum (1) | 2022.10.05 |
[Java] 추상(Abstract) 클래스/메서드 (0) | 2022.10.05 |
[Java] 싱글톤 디자인 패턴(Singleton Design Pattern) / final 키워드 (0) | 2022.10.05 |
[Java] static (0) | 2022.10.05 |