interface
- 프로그램과 사용자를 연결해주는 매개체
- 자동으로 static(상수), abstract(추상메서드) 생성
가지고 있는것: 상수, 추상메서드, default(1.8이후), static 메서드
못가지는 것: 클래스X → 객체생성X, 일반변수X, 일반메서드X, 생성자X
클래스는 다중 상속을 지원하지 않는다.
interface 왜 생겼을까?
여러곳에서 같이 사용하는 것들을 interface 구조로 정의하고, 추상메서드로 기능만 정의 해 놓으면
자식 클래스에서 그 추상메서드를 무조건 오버라이딩해서 완성시켜줘야 함
결론적으로, 자식 클래스에서 다양하게 변형시켜서 사용가능
예시
day09.inter.basic
- interface1, interface2에 각각 추상메서드 method01, method02가 있음
- 추상클래스를 상속(구현)하는 자식클래스 Basic안에 오버라이딩 해야하는 method01, method02 완성하기
// interface는 객체 생성이 불가하고, interface타입의 변수를 만들어서 Basic객체를 생성할수는 있으나 메서드 사용은 그 interface에 있는 것만 사용 가능 ex) inter1 → method01,inter2 → method02
- main클래스에서 참조변수 b에 대한 Basic객체 생성 - b.으로 오버라이딩된 method01, 02 호출하기
- b(new Basic)를 inter2타입의 참조변수 i2에 넣는 것 가능 (클래스 형변환, 업캐스팅으로 타입 생략 가능)
- b(inter2)를 자식객체인 Basic타입의 변수 bb에 넣으려면 클래스 형변환이 필요(다운캐스팅으로 생략 불가)
day09.inter.basic2
iterface 타입으로 자식 클래스 객체 생성 가능!
BasicInter b = new Basic();
기능
1. 다중 상속을 지원
2. 메서드 명세서
- interface IPet - Dog, GoldFish 상속관계 = Dog클래스: Dog타입, IPet타입 / GoldFish클래스: GoldFish타입, IPet타입
- Animal - Dog 상속관계 = Animal클래스: Animal타입, Dog타입
- Fish - GoldFish 상속관계 = Fish클래스: Fish타입, GoldFish타입
- 결론적으로, Animal - IPet - Fish는 서로 형변환 가능
다중 상속
- interface간에도 상속이 가능
- interface간의 상속은 extends 이용
머리 위의 모든 추상클래스들을 오버라이딩 해야함
day09.inter.basic3
abstract class Animal / Fish - 추상메서드 eat, swim
package day09.inter.basic3;
// Animal
public abstract class Animal {
public abstract void eat();
}
// Fish
public abstract class Fish {
public abstract void swim();
}
interface class IPet - 추상메서드 play
package day09.inter.basic3;
// IPet
public interface IPet {
void play(); // ....
}
자식 class Dog / Cat / Tiger(interface 연결x) - 각각 속성받은 추상메서드들을 오버라이딩
package day09.inter.basic3;
// Dog
public class Dog extends Animal implements IPet{
@Override
public void eat() {
System.out.println("강아지는 사료를 먹어요");
}
@Override
public void play() {
System.out.println("강아지는 마당에서 놀아요");
}
}
// Cat
public class Cat extends Animal implements IPet{
@Override
public void eat() {
System.out.println("야옹이는 생선을 먹어요");
}
@Override
public void play() {
System.out.println("야옹이는 거실에서 놀아요");
}
}
// Tiger - interface하고 연결X
public class Tiger extends Animal{
@Override
public void eat() {
System.out.println("호랑이는 고기를 먹어요");
}
}
자식 class GoldFish / Shark(interface 연결x) - 각각 속성받은 추상메서드들을 오버라이딩
package day09.inter.basic3;
// GoldFish
public class GoldFish extends Fish implements IPet{
@Override
public void swim() {
System.out.println("금붕어는 강에서 놀아요");
}
@Override
public void play() {
System.out.println("금붕어는 어항에서 놀아요");
}
}
// Shark - interface하고 연결X
public class Shark extends Fish{
@Override
public void swim() {
System.out.println("상어는 바다에서 놀아요");
}
}
PetHouse - 상속 관계 X
package day09.inter.basic3;
public class PetHouse {
// 1. IPet타입을 매개변수로 받아서 기능을 출력하는 static 메서드
public static void house(IPet p) {
p.play();
}
// 2. IPet[] 타입을 받아서, 배열 내무 Pet들의 play기능을 실행하는 메서드
public static void house2(IPet[] arr) { // 배열이니까 매개변수도 배열로 맞추기
for(IPet i : arr) {
i.play();
}
// 기본 for문으로 선언
// for(int i = 0; i < arr.length; i++) {
// arr[i].play();
// }
}
}
- interface로 상속관계를 줘야하는 클래스 X
- 문제 그대로 IPet타입(interface)을 매개변수로 받는 메서드 생성 - public static void house(IPet p) { }
매개변수를 받아서 기능 출력 p.play() - 매개변수를 받기 때문에 p, 메서드 호출하려면 .사용 - IPet[ ] 배열타입(interface)을 매개변수로 받는 메서드 생성 - public static void house(IPet[ ] arr) { }
향상된 for문 [배열의 값을 담을변수 선언: 배열이름] IPet 변수 i를 배열에 넣으면서
i.play(); 실행
main
package day09.inter.basic3;
public class MainClass {
public static void main(String[] args) {
// Dog d = new Dog(); // eat, play
// Animal d = new Dog(); // eat
IPet d = new Dog(); // play
// 위의 세줄이 다형성임
Animal baduk = new Dog();
Animal nabi = new Cat();
Animal hodol = new Tiger();
// 1. Animal배열에 저장
Animal[] arr = {baduk, nabi, hodol };
for(Animal a: arr) { // Animal타입 a을 배열에 넣어주기
a.eat();
}
// 2. baduk은 Animal이지만 생성된 클래스가 인터페이스 상속을 받고 있다면, 상호형변환이 됩니다.
IPet i1 = (IPet)arr[0]; // 바둑
IPet i2 = (IPet)nabi; // 나비
IPet i3 = new GoldFish();
IPet[] arr2 = {i1, i2, i3};
for(IPet i: arr2) { // IPet타입 i를 배열에 넣어주기, 기본 for문도 사용해보기
i.play(); // 메서드 호출할 때 . 사용
}
// 3. PetHouse
PetHouse.house(i1); // static 썼기 때문에 클래스이름.메서드 이름 사용
PetHouse.house(i2);
PetHouse.house(i3);
PetHouse.house2(arr2);
}
}
------------------------------------정답----------------------------------
강아지는 사료를 먹어요
야옹이는 생선을 먹어요
호랑이는 고기를 먹어요
강아지는 마당에서 놀아요
야옹이는 거실에서 놀아요
금붕어는 어항에서 놀아요
강아지는 마당에서 놀아요
야옹이는 거실에서 놀아요
금붕어는 어항에서 놀아요
강아지는 마당에서 놀아요
야옹이는 거실에서 놀아요
금붕어는 어항에서 놀아요
day09.inter.default_
- 인터페이스에서 doubl PI는 상수, void some1()은 추상메서드로 정의
- 인터페이스 MyInter를 상속받는 MyClass에서 some1()은 무조건 오버라이딩 해야 함
- 메인클래스에서 인터페이스 타입으로 자식 객체 생성 가능
- default 메서드 - 인터페이스에도 몸체를 가지는 메서드 선언이 가능
몸체가 있어서 오버라이딩 안해도 되고, 기본 메서드처럼 사용가능 = 상속이 됨 / i. 사용가능 - static 메서드 - 상속이 불가, MyInter.으로 직접 불러야함
Quiz15
package quiz15;
public interface SongList {
public void insertList(String song);
public void playList();
public int playLength();
}
package quiz15;
public class MelonMusic implements SongList{
private String[] list = new String[100];
private int count = 0;
/*
* SongList인터페이스를 상속받아서 기능을 구현합니다.
* insertList() 는 list배열에 순서대로 저장
* playList() list의 음악을 랜덤하게 출력
* playLength() 는 저장된 음악의 개수를 반환
*/
@Override
public void insertList(String song) { // String song을 입력하면
// 반복문 사용하면 한번 쓸 때 배열 100개에 그것만 다 들어감
list[count] = song; // list[0]부터 하나씩 배열값으로 들어감
count++; // count 하나씩 추가하면서 인덱스 0,1,2,3,4...
}
@Override
public void playList() {
// 곡이 없을 때 없다고 출력
if(count == 0) {
System.out.println("곡이없음");
return;
}
for(int i = 0; i < count; i++) {
int ran = (int)(Math.random()*count);
System.out.println(list[ran]);
// 랜덤한 한곡만 출력
// int song = 0;
// for(int i = 0; i < count; i++) {
// int ran = (int)(Math.random()*count);
// song = ran;
// }
// System.out.println("현재곡: " + list[song]);
}
}
@Override
public int playLength() {
return count;
}
}
package quiz15;
import java.util.Scanner;
public class MainClass {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
// 바깥에 객체생성: 재황용하려고, while문 안에 들어가면 돌때마다 새롭게 됨
SongList s2 = new MelonMusic();
while(true) {
System.out.println("메뉴[1.추가, 2.재생, 3.개수, 4.종료]");
System.out.print("> ");
int num = scan.nextInt();
if(num == 1) {
System.out.print("노래> ");
scan.nextLine();
String name = scan.nextLine();
s2.insertList(name);
} else if(num == 2) {
s2.playList();
} else if(num ==3) {
int len = s2.playLength();
System.out.println("재생곡 개수: " + len);
} else {
System.out.println("종료");
scan.close();
return;
}
}
// 내 풀이
// SongList s2 = new MelonMusic();
// s2.insertList("Pink Venom");
// s2.insertList("불장난");
// s2.insertList("블랙핑크");
// s2.playList();
// System.out.println(s2.playLength());
}
}
오늘 하루
기억에 남는 부분
- 인터페이스하면 자식 클래스에서 그 추상메서드를 무조건 오버라이딩해서 완성시켜줘야 함
큰 틀이 하나 있고 여러 회사에서 다양한 설계 가능하게
- 인터페이스도 데이터타입(부모 타입)이 될 수 있음
어려운 부분
- 향상된 for문을 정확히 어떻게 써야할 지 모르겠음
- day09.inter.default_: default메서드와 static메서드의 차이를 알고, 출력할 수 있어야함
문제 해결 부분
- quiz15 곡을 한곡만 랜덤하게 출력해봄
'프로그래밍 언어 > Java' 카테고리의 다른 글
[Java] API_ java.lang (문자열, Math 등) (0) | 2022.10.18 |
---|---|
[Java] 예외 처리 (try ~ catch ~ finally), throws & throw (0) | 2022.10.17 |
[Java] 제어자 (static, final, abstract) (0) | 2022.10.13 |
[Java] 키워드 this & super, 접근제한자(public, private) (0) | 2022.10.07 |
[Java] overriding(재정의), overloading(중복) (0) | 2022.10.07 |