동적 바인딩과 추상화

윤주헌's avatar
Aug 13, 2024
동적 바인딩과 추상화

1. 프로젝트 생성

notion image

src?

소스코드
notion image

클래스 생성 방법

notion image
 

2. 객체지향의 핵심

💡
객체는 상태와 행위를 가진다. 상태는 행위를 통해서만 변경한다
상태 = 변수(어떤 변수? 스택의 변수X 객체가 생성될 때 지니고 있는 변수)
상태만 가진 애를 객체라 안 한다 그냥 데이터 덩어리다(객체라 부르기는 하지만 엄밀히 말하면 아님)
 

1. 공간에 대해서

notion image
🧮
2진수 10진수 변환 방법(정리하기)
static, heap, stack 예시
static, heap, stack 예시

2. 예시

💡
static이 안 붙어 있는 애들은 무조건 heap에 생성된다 메서드안에 들어가는 애가 stack에 들어간다 {} 중괄호가 끝나면 사라지는 애들
package ex00; class 엘리스{ private int 목마름;//스테틱 없어서 동적으로 new 해서 heap에 띄워야 한다 //alt + insert로 만들 수 있다. public 엘리스(int 목마름) { this.목마름 = 목마름; } //setter 상태 변경하는 애 의도를 파악할 수 없는 행위기에 세터는 직접 만드는게 좋다 //이게 의도를 파악하기 쉽다 //메서드 물마시려면 내부 로직은 아주 복잡하다 //static에 안 붙어 있기에 무조건 heap에 뜬다 new 할 때 뜬다.@@@@@@@@@@@@ void 물마시기() { 목마름 = 0; } // 이 친구를 getter 상태를 확인하는애 int 목마름확인하기(){ return 목마름; } } public class Mem01 { public static void main(String[] args) { 엘리스 e = new 엘리스(100);// 이 라인에서 동적할당(heap) // 1. 값 변경(행위) 의도한 값이 나온다 0 e.물마시기(); // 2. 값 확인 int 목마름 = e.목마름확인하기(); System.out.println(목마름); // e.목마름 = 100;//상태는 행위로 들어가야 한다 그래서 틀렸다. //private을 해줘서 마음대로 못 만든다 //객체 초기화는 태어날 때 해야함 태어날 때 아버지가 있는거지 20살때부터 아버지가 있는게 아님 //new 엘리스를 초기화 해줘야 함 } }
 

3. 상속과 컴포지션

3.1 상속

💡
기존의 클래스에 기능을 추가하거나 재정의하여 새로운 클래스를 정의하는 것을 의미합니다.
이러한 상속은 캡슐화, 추상화와 더불어 객체 지향 프로그래밍을 구성하는 중요한 특징 중 하나입니다.
is 관계다
 
Car클래스가 있고 Sonata extend Car 이라면
Car s1 = new Sonata();
이러면
 
notion image
Sonata s1 = new Sonata();
notion image
 
notion image

3.2 컴포지션

 

4. 추상화란?

다형성 is, has
상속을 하면 여러가지 타입을 추상화 할 수 있다
추상화는 이 세상에 존재하는게 아니고 그냥 부르기 편하게 있기 위해 있는 것이다
class Car{ //상태 행위 void a (){ System.out.println("hi"); } } class Sonata extends Car{ //상태 행위 void b (){ System.out.println("sonata"); } } class Genesis extends Car{ // 상태 행위 void c (){ System.out.println("genesis"); } } public class Mem02 { public static void main(String[] args) { Sonata s1 = new Sonata(); Genesis g1 = new Genesis(); 이때는 s1.a(); s1.b(); g1.a(); g1.c(); Car s1 = new Sonata(); // 메모리에 sonata, car Car g1 = new Genesis();// genesis, car s1.a(); g1.a(); } }
Car는 sonata인가? 맞음 Car는 Genesis인가 맞음
public class Mem02 { static void 레이싱(Sonata s1){ System.out.println("소나타 달림"); } static void 레이싱(Genesis s1){ System.out.println("제네시스 달림"); } }
이렇게 두 개를 다 만들 필요가 없다
static void 레이싱(Car s1){ System.out.println("제네시스 달림"); }
Car만 해주면 두 개 다 만들 필요가 없다 근데 sonata인지 genesis인지는 모르기에
static void 레이싱(Car s1){ if(s1 instanceof Sonata){ }else if (s1 instanceof Genesis){ } }
해주는데 이러면 새로운 객체를 만들 때 마다 if해줘야 하는 번거로움이 생긴다 그래서

5. 동적 바인딩

재정의
(부모의 매서드 이름과 자식의 매서드 이름과 같다.)부모의 메서드 오브라이딩(무효화)한다 그래서 자식클래스 동적바인딩해서 재정의한다
abstract class Car{//자동차 달려주세요 하면 자동차 들이 다 달리기 시작한다) //Car c = new Car()할 수 없다 추상화 시켰기 때문에 객체 못만듬 abstract void run(){} 통로의 역할로만 사용함 } class Soanata extends Car{ void run(){ System.out.println("소타나 달린다"); } } public class Mem02{ //추상화 안하면 레이싱에 sonata, genesis 두개를 만들어야 한다 static void 레이싱(Car car){ car.run(); 하면 부모의 run 무효화하고 자식의 run사용가능(동적바인딩) } }
어떻게 달리는지 어떤 차가 달리는지 모르기 때문에 abstract를 추가해서 만든다.
💡
클래스에 abstract하는 이유는 추상적인 것이기에 객체가 있으면 안되기 때문
💡
메서드에 abstract하는 이유는 상속 받는 객체가 반드시 Override해줘야 하기 때문(동적바인딩)
 
package ex00; abstract class Car { // car 상태 // car 행위 abstract void run(); // 무효화 } class 티코 extends Car{ void run() { System.out.println("티코 달린다."); } } class Sonata extends Car{ // 다형성 // Sonata 상태 // Sonata 행위 void run(){ // 재정의 System.out.println("소나타 달린다"); } } class Genesis extends Car{ // 다형성 // Genesis 상태 // Genesis 행위 void run(){ System.out.println("제네시스 달린다"); } } class 페라리 extends Car{ @OVerride void run(){System.out.println("페라리 달린다");} } 이게 생긴다면 elseif 기존 코드 손봐야 한다 public class Mem02 { static void 레이싱(Car car){ //이게 dip 티고 car하면 구체적인 것에 의존하게 된다 car.run(); } public static void main(String[] args) { Car s1 = new Sonata(); // Sonata, Car Car g1 = new Genesis(); // Genesis, Car Car t1 = new 티코(); 레이싱(t1); } }

정리?

💡
선생님이 여러명 있는데 나가라 할 때 누구 선생님 나가세요, 누구 선생님 나가세요 안하고 선생님 나가세요 만 하면 모든 선생님들 나간다. 즉 선생님이라는 추상화를 묶는 것
Share article

code-sudal