[24.06.21] JAVA_인터페이스, 중첩 객체

ANGELA·2025년 1월 8일

[KB]학습내용정리

목록 보기
5/57

01. 인터페이스

  • 초기에는 추상 메서드밖에 없었음
  • 거의 public 쓴다
  • 일종의 추상 클래스다 → 인스턴스 못 만든다 → new 못해요
  • 전략 패턴이다
  • 상속의 다형성과 동일한 구조 → 다중 상속 문제때문에 인터페이스가 필요하다.

1. 개념

  • 규격만 정의
  • abstract 클래스에 해당한다 → 실체가 없다
  • 디폴트 : abstract → 그래서 주로 생략한다

2. 쓰임

  • 팀 프로젝트할때, 구두로 말고 언어로 딱 정의 내린거다.
  • 만드는 쪽에서, 형태 만들어졌으니까, 정의만 내리면 된다.
  • 완성되면 2개 결합
  • 사용자측에서는 형태만 본다
  • 이렇게 만들자 약속해놓고, 각자 만든다.

3. 추상 메서드

  • 코드 블록 없음
  • 메서드의 모양만 정의

4. 구현 클래스

  • 키워드 : implements
  • 상속이랑 비슷한 구조
💡 버전 7까지 여기까지밖에 없었음 → v8 에서 여러가지 기능들이 생겼다 - 우리가 보는 자바는 v7 - 이해를 위해서 v8 기능은 알고 있어야 한다.

※ 클래스 다이어그램

  • 추상은 이태릭체
    interface 는 <<>> 안에
  • 구현은 점선으로
  • 스테레오 타입 : 인터페이스

  • concrete : 구현 클래스

02. 다중 인터페이스

  • 우리가 이제 실전에서 쓸것들이다.
  • 다중상속 보완한다.
  • 개수 제한 없음
  • 오버라이딩 구현에서 다 해야한다.

1. 인터페이스 분리 원칙

  • 단일책임원칙에 맞게 분리
  • 서로 다른 기능이면 분리해야한다.

2. 상속 가능 → 다중상속도 가능

  • 자동 타입 변환 가능 : 상속이랑 똑같다

3. 다형성

  • 상속을 바탕으로 이루어진다.
  • 디스코프 치환 원리
    • 자식을 부모로 치환해서 부모로 쓴다.
    • 디스코프가 만들었다.
  • 클래스 다이어그램

4. 결합도는 낮추고, 응집도는 높인다.

  • 결합도 : 디스코프 치환 원리로 부모 자식 나눈다.
  • 응집도 : 단일책임 원칙 지킨다.

03. solid 원칙

  • srp ocp 리스코프치환원리 interface분리원칙 dependency injection(DI)
  • s가 제일 중요하다 → srp가 위배되면 다 위배된다. 지켜야한다.

1) 단일 책임 원칙

  • 추상화를 속성으로 하면 안되고, 속성을 다 포함하는 무언가로 만들어놔야한다.

2) 개방 폐쇄 원칙

  • 사용자 측은 변화 없다
  • 인터페이스에서 기능 확장

3) 리스코프 치환 원칙

  • 부모꺼 상속받아서 자식이 부모 역할한다

4) 인터페이스 분리 원칙

  • 인터페이스 내에서 단일 원칙 지킨다.
  • 사용자측은 인터페이스 딱 한개에만 의존해야한다.
    - 예시 ) 프린터 쓰려면 프린터블에만 의존 / 스캐너 쓰고 싶으면 스캐너블 운영

5) 의존 역전 원칙

  • 나 이거 필요해하면 자동으로 해준다.
  • 매개변수쪽에는 인터페이스로 미리 해놔야한다.
  • spring의 기본 원칙
  • 인터페이스로 프로그래밍해라! → 객체지향에서 중요하다!

04. 클래스 다이어그램

업로드중..


05. 오후수업

이론정리게시판

## 1교시 인터페이스
>> 추상메서드
1. abstract 안붙여도 인터페이스는 디폴트가 추상메서드이다 (본문없이)
2. 다형성의 달성을 위해서 사용한다 (상속과 오버라이딩)
3. 필드는 public static final 이 기본값임
4. 생성자, main 메소드는 사용 불가, default 메서드는 this 가 있다고 가정, this로의 접근은 불가

## 2교시 인터페이스
> default, this
메소드 중에 상속된 클래스의 인스턴스의 기본 메서드를 default 키워드로 제공 가능
this로의 접근은 불가 (this.x 불가)
기본 메서드는 다양한 명칭으로 불림
default method == defender method == virtual extension method

> Static method
인터페이스에는 클래스의 정적 메서드와 유사한 static 메서드도 있을 수 있습니다.

defulat method & multiple inheritance
구현된 두 인터페이스 모두 동일한 메서드 시그니처를 가진 기본 메서드를 포함하는 경우
구현 클래스는 사용할 기본 메서드를 명시적으로 지정하거나 기본 메서드를 재정의(override) 해야 합니다.
> 예시 :

interface A {
   public default void display() {
      System.out.println("AAAA");
   }
}
 
interface B {
   public default void display() {
      System.out.println("BBBB");
   }
}
 
// 오버라이딩 되지 않은 경우
public class InterfaceExample implements A, B {
  //   이럴때는 오버라이딩 해서 쓰면됨
//     @Override
//     public void display() {

//             A의 display를 쓰겠다
//         A.super.display(); 
//             B의 display를 쓰겠다
//         B.super.display(); 
//           혹은 아예 재정의
//   			System.out.println("CCCC");
//     }
   public static void main(String args[])
   {
      InterfaceExample obj = new InterfaceExample();
      // A의 display를 실행해야 하는 지, B의 display를 실행해야 하는 지 알 수 없어 에러가 남
      // 호환불가    
      obj.display();
   }
  

}

private 메서드는 default 메소드에서 사용 가능
private static 메서드는 default 메소드와 static 메소드에서 사용 가능

default메서드와 static 메서드의 차이

부모타입으로 자식 인스턴스를 이용할 수 있다 LSP (Liskov substitution principle)

## 실무 case
다형성을 이용하고 싶다면 extends 대신 인터페이스로 implements 하여 interface 타입으로 사용하기를 권하며, 
상위 클래스의 기능을 이용하거나 재사용을 하고 싶다면 
상속(inheritnace) 보단 실체화(realization) 를 권장 
>> 차에 타이어 인터페이스 타입으로 인스턴스화(new) 하는 방식 [Has-a 관계]
예시 :
class HankookTire implements Tire {
	//추상 메소드 재정의
	@Override
	public void roll() {
		System.out.println("한국 타이어가 굴러갑니다.");
	}
}

class KumhoTire implements Tire {
	//추상 메소드 재정의
	@Override
	public void roll() {
		System.out.println("금호 타이어가 굴러갑니다.");
	}
}

class Car {
	//필드
	Tire tire1 = new HankookTire();
	Tire tire2 = new KumhoTire();

	//메소드
	void run() {
		tire1.roll();
		tire2.roll();
	}
}

public class CarExample {
	public static void main(String[] args) {
		//자동차 객체 생성
		Car myCar = new Car();

		//run() 메소드 실행
		myCar.run();

		//타이어 객체 교체
		myCar.tire1 = new HankookTire();
		myCar.tire2 = new KumhoTire();

		//run() 메소드 실행(다형성: 실행 결과가 다름)
		myCar.run();
	}
}


## 3교시 UML / SOLID
클래스 다이어그램 참고사이트] https://mermaid.js.org/syntax/classDiagram.html
Has-a (realization)
Is-a (Inheritance)

### 정적 메소드
메소드명 앞에 static 키워드 붙는다
인스턴스를 만들지 않아도 클래스에서 바로 메소드를 사용할 수 있게 해준다
메인 메소드는 정적 메소드인가요?
네
왜? 앞에 static키워드를 사용했고, 인스턴스 없이 실행가능하니까

### 추상 메소드
인터페이스를 정의할 때는 모두 추상 메소드이다
재정의(Overriding) 해서 써야 한다
오버라이딩 ⇒ 재정의
달리다를 오버라이딩을 했다고 하면?
사람이 달린다를 개가 달린다 라고 구체화 시킬 수 있음
실제로 상속받아서 (implemets 구현해서 사용) 사용한다

## 디폴트 메소드
실체화된 인스턴스가 구현된 인스턴스가 this일 것이다 하고 실현이 되는 것
추상 메소드는 본래 본문이 없음 누군가가 실제로 구현(implemnt, extend)해서 사용하는 것
즉, 기능이 없고 이름만 있다 (본문이 없는 모습)
* 상속을 받거나 구현을 했을 때 실제로 정의해서 사용해야 한다
디폴트 메소드는 본문을 작성 할 수 있음
인스턴스가 나를 상속(extend, implement) 받은 자식을 가르키게 된다
다만 자식이 어떤 것을 가지고 있는지 모른다. 접근이 불가능하다는 뜻 (this.xxx 은 디폴트 메소드 안에서 사용할 수 없음)
상속받은 애가 어느정도 부수적인 기능을 할 수 있도록 구현을 해놓았다
추상 클래스 → 추상 메소드 구현
본문: 자식 A에도 System.out.println 했고 자식 B에도 하는 출력문을 계속적으로 작성해야함
불편.... 디폴트 메소드에다가 1999줄 작성하고 나머지 한 줄만 너가 채워서 써!
이런 기능들을 미리 정의 할 수 있도록 하는 것이 디폴트 메소드

### private 메소드
상속을 받았거나 구현을 했을 때 이 메소드를 쓸 수 있나요?
못 쓴다
왜? sub 클래스가 부모 클래스로 접근 할 수 없도록 막아버림 (접근 제한)
실제로 자식을 만들었을 때 실체는 있지만 접근은 못 함
프라이빗 필드는 자동 완성으로 안 나옴 → 인텔리제이에서
접근 할 수 있는 메소드 하나를 정의해서 쓰고는 한다 (캡슐화 적용) getXxx() 로 만들어 씀
private 키워드를 사용하더라도 본인 클래스 안에서는 접근할 수 있다는 원리를 이용해서
자식을 실제로 인스턴스화 했을 때 x는 접근 못하지만 getX() 는 접근 가능하도록 함
⇒ getter와 setter의 역할
캡슐화로 인해서!
불필요한 속성은 숨기고, 원하는 기능만 보게 해 주는 것
getter만 있으면 수정 불가 (setter 메소드가 없으면 수정할 방법이 없음) readonly로 만든다는 의미
getter + setter도 있으면 수정 가능

정리 하자면...

## 정적 메소드 (Static Method)
사용법: 클래스명.메소드명()
특징: 인스턴스 생성 없이 사용, 클래스 레벨에서 공유
## 추상 메소드 (Abstract Method)
사용법: abstract 키워드 사용
특징: 선언만 하고 구현은 없음, 상속받은 클래스에서 반드시 구현
## 디폴트 메소드 (Default Method)
사용법: default 키워드 사용
특징: 인터페이스에서 기본 구현 제공, 필요시 오버라이드 가능
## 프라이빗 메소드 (Private Method)
사용법: private 키워드 사용
특징: 클래스 내부에서만 접근 가능, 캡슐화된 내부 동작
각 키워드는 객체 지향 프로그래밍의 다양한 원칙과 패턴을 구현하는 데 사용되며, 특정 상황에서 올바르게 사용하는 것이 중요합니다. 이를 통해 코드의 재사용성, 유지보수성, 가독성을 높일 수 있습니다.

질문게시판

public default private protect의 개념은 이해가 되지만..
각각 언제 활용해야되는 것인지에 대해 잘 모르겠어요
그냥 저희가 프로그램 코드를 작성할 때 속성들의 접근 범위를
지정하고 싶은데로 사용하면 되는 것인가요?
어떤건 private으로 선언해야되! 같은 규칙이 있는 건 아닌거죠?
  
> 규칙이 있긴 있어요 : 사용할 수 있는 접근 제한자가 정해져 있다
> 다만 용도는 접근제한
ex ) Class public / default(안씀)
  >> Inner Classprivate Class 가능
--------------------
  저희가 실습에서 사용하는 private는 원래
  사용하면안되는 private인건가요?
> 상속을 못하게 되는 경우에는 private를 제거해주어야 할거에요
--------------------
   @Override 꼭 써야만 하나요?
>1. Override 어노테이션이 있으면 다른 개발자가 이 메소드가 인터페이스에서 오버라이딩 되었다는걸 쉽게 알 수 있어요
 interface 파일을 열어보지 않아도 된다는 뜻이기도 합니다
>2. 컴퓨터가 Override 어노테이션을 썼는데 interface 에 이 메소드가 없을 경우에 알려줘요
  너가 오버라이드 하려는 메소드가 인터페이스에는 없다. 라고
--------------------
  new 연산자로 객체를 생성할 때 객체를 왜 초기화 하나요
  1. 초기값이 정해지지 않은 경우를 방지할 수 있습니다
  2. 반드시 초기화 하지는 않아도 됩니다 lazy하게 객체부터 만든 후 setter를 사용하기도 합니다
--------------------
  자바에서의 this 키워드는 클래스로 만들어진 인스턴스입니다.
  예시 :
  public class Animal {
  	String name;
  	Animal(String name) {
    	this.name = name;
    }
  }
  
  public class Main {
  	public static void main(String[] args) {
    	Animal a1 = new Animal("동물1");
        Animal a2 = new Animal("동물2");
    }
  }
--------------------
컴퓨터 입장에서 NaN값과 Null 값을 같게 판단하는지 다르게 판단하는지 궁금합니다.
> 언어에 따라 다릅니다
java util에서 Objectsimport하고 isNull() 메소드를 사용하는데
isNull에 NaN값이 들어가면 true를 반환하는지 false를 반환하는지 궁금합니다.
> false
--------------------
// 인터페이스 변수 선언
RemoteControl rc1;
RemoteControl rc2;

// Television 객체 생성하고 인터페이스 변수에 대입
rc1 = new Television();
rc1.turnOn();
rc1.setVolume(5);
rc1.turnOff();

// Audio 객체 생성하고 인터페이스 변수에 대입
rc2 = new Audio();
rc2.turnOn();
rc2.setVolume(11);
rc2.turnOff();
        
이런 식으로 하면 Television을 가진 rc1 인스턴스가 사라지지 않고 rc1과 rc2를 계속 쓸 수 있는 것 맞나요?
--------------------
### 추상
인터페이스: 메소드 디폴트가 public이라 안써도 됨
구현: public 메소드 써야됨

### 디폴트
인터페이스 : default 메소드에서 함수 선언 가능
구현 : public 메소드

### 정적
인터페이스 : static 메소드
구현 : 필요없음

### main : 바로 호출 가능
### 클래스 this는 클래스에서 만들어진 인스턴스를 가리킨다.
profile
혼자 보려고 만든 기록장 | 또또는 귀여워 🐈‍⬛

0개의 댓글