배움 __IL/TIL 1기

TIL : 15번째- 221219 [12-3-월]

Mo_bi!e 2022. 12. 19. 19:29

I. INTRO : 이전 복습 (ㄴㅈㅊㅈ / ㅊㅈ / ㄱㄱ)

OOP는 구현보다는 필요성과, 이유를 알자

함수 4가지를 암기(ㄴㅈㅊㅈ)하기보다 느껴야한다.

 

데이터의 속성을 구조화 (우리 머릿속의 개념과 유사한)한것을 구조체라고한다.

<구조체를 이용하지않을 경우 문제점 두가지? :충주>

 

문제점1. 변수명 충돌될 수있음 

/문제점2.(가장 중요한)묶어서 쓰면 주석을 써야하는데 주석 대신에 데이터의 공통분모에 대한 범주화가 가능

/3. (내 생각 : 변수누락을 막을 수있다) 

 

이후 구조체 이후에 객체지향프로그래밍이 탄생함 <구조적프로그래밍 문제점> 때문임 (고기)

문제점 1 : 함수를 나누는 '기'준이 명확하지 않음(사람마다 최적화된 나눔의 기준이 없음)

/ 문제점 2 : 함수의 '고'립도를 무너뜨린다. (결합력을 너무 강하게 만든다) 

 

 

II. 객체지향형 (고기)

1. 코드파일 관리방법

(1) 캡슐화 정리 : 데이터 구조함수 하나의 영역에 함께 - 정보은닉

 

함수를 쓰고있는 파일때문에 함수 재정비가 어렵다. 변화주는 운신의 폭을 주는게 바람직, 이러한 문제점 해결위해서/ 변화줄때 어떤곳에서 어려움 있는지?

수정방법 : 지금까지는 함수를 어디에 두는지 규칙이없었는데, 이제 특정한 곳에 두라고 지정을 한다. (캡슐화 : 데이터 구조에 따른 코드의 수정범위캡슐 범위로 한정할 수있다.)

 

 

-- 본인 객체지향 이해 X C로 함수로 개발, 문제 있음/ 문제를 수월하게 해결하기 위해서 자의적으로 특정부분마다 파일을 따로함 지나보고니 이것이 캡슐화같은것

 

(2) 객체지향 프로그래밍

실세계(real world)의 일들을 '객체를 사용'해서 모델링

 

(3) 구조를 먼저 생각하는 프로그래밍

 

부동산개발 : 기획, 설계, 건축, 유지관리

 

ex: 오목판 [ 오목판 출력한다 (오목판 : 대상 / 출력: 행위)]

이 문구 그대로 기능 구조체 대상으로 묶어 준다.

 

오목판을. (출력) => 캡슐

출력 => 기능

이제부터 내가 설명하는 것에서 하는 행위명이 함수이다

 

(4) 개체란?


- [이미지]보고 객체 + 행위 잡아내기

객체 행위
농부 일을끝내다./ 쉬다. /탈곡하다.
자동차 지나가다. / 다가오다.
행인 물동이를 지다/ 가다.
떠있다.
비행기 날아가다.

그외 구름, 나무 등은있는데, 이들은 '행위'가 없이 고정되어있다. (객체가 아님 배경임)

즉 객체지향에서 말하는 캡슐화행위 기준이다.

 

-이러한 행위를 잡아내는데에는 인문학적 역량이 필요하다. 이러한 것이 OOP의 기본 구조이다.

 

식별 목적이름은 객체 vs 타입을 말하는거면 개체

중국집 메뉴판 자장면과 vs 주문한 자장면

(like 영어 boy VS a boy : 관사여부로 실존을 달리 함)

 

(5) 개체의 속성이란?

비행기 : 개체 (자바는 개체를 클래스로 구현)

이것을 객체를 만들 때 속성이 들어간다.

객체지향에서는 어떤 행위를 담당하는지가 중요, 속성은 구현하는데 따라오는 녀석에 불과

 

모든 객체는 실제 이름과 상관없이 내부에는 hcod(해시코드 : 객체 식별코드 - 가바지클렉션과 연관)를 가지고있다.

그 외 속성 x,y,size,direction,visible,speed 가 있다

 

 

 

2. 실습 (CapsuleTest.class)

함수로 구현보다, 말하는 것처럼 구현되는 객체지향형으로 (너희가 말하는대로 근접하게 말해줄게 : so easy) 

 

(1) 실세계를 반영한 표현의 변화에 대한 필요성

1)  행위의 관점

Function < = > method (실세계 반영)

함수는 누가 해도 정의하기가 어려운데,

메소드로는 '비행기 날라다닌다' 처럼 표현(행위)하는대로 객체 지향이므로 그대로 표현이 가능하다.

 

같은것을 다르게 표현하기 위한 차이점이 있다.

 

2) function 정의와 method 와 차이

package ex5.capsule;

import java.util.Scanner;

public class CapsuleTest {

	public static void main(String[] args) {	
		//성적입력받기위한 대상 먼저!

//		성적 객체를 준비한다
		//성적 뉴렉성적 = new 성적();
		Exam examl = new Exam();
		
//		성적을 입력받는다.
		inputExam(examl); //객체지향 스럽지 X
		examl.input();
		
//		성적을 출력한다.
		printExam(examl); //객체지향 스럽지 X
		examl.printExam(); //인스턴스 메소드
		
	}

	//static 인스턴스로 호출된 함수로 오해할까봐 있음
	//따로해야한다
	//인스턴스 함수가 아니끼 때문에 this가 안됨
	
	private static void printExam(Exam exam) {
		// TODO Auto-generated method stub
		int kor = exam.kor; //이렇게 넘겨받음
		
		System.out.println("\n단독객체");
		
		System.out.printf("점수는  ");
		System.out.print(" 국어: " + kor);
		System.out.print(" /영어: " + exam.eng);
		System.out.print(" /수학: " + exam.math);
		System.out.println();
		System.out.print("\n====================\n");
	}

	private static void inputExam(Exam exam) {
		// TODO Auto-generated method stub
		
	}

}

성적 입력과 관련해서 functionmethod 로 둘다 함수를 호출이 가능하다.

함수의 호출은 : 함수명(객체 : 매개변수) [괄호를 통한 고전적인방식]

메소드의 호출은 : 인스턴스.메소드()

로 호출방식의 차이가 있다.

 

이런방식을 생각하면 real world (실세계)는 실제로 존재하는 것(실존 : 인스턴스)가 메소드(행위)를 하는것이다.

객체를 중심점으로 잡고, 행위를 하게끔 하는 것으로 접근하는 것이다.

 

한편 일반 함수의 경우 static을 써서 인스턴스로 호출된 함수(메소드)구분이 어려울 수 있으므로 지정해주어야한다.

특히 이 경우 인스턴스함수가 아니기 때문에 this 가 불가능하다.

 

3) 메소드 정의

package ex5.capsule;

public class Exam {

    int kor;
    int eng;
    int math;
    //이걸로 변수나, 객체를 선언이 가능하다
    public void input() {
        // TODO Auto-generated method stub


    }
    public void printExam() {
        // TODO Auto-generated method stub
        int kor = this.kor; //이렇게 넘겨받음
        // this (인스턴스 이것)을 넘겨받는다!

        System.out.println("\n단독객체");

        System.out.printf("점수는  ");
        System.out.print(" 국어: " + kor);
        System.out.print(" /영어: " + this.eng);
        System.out.print(" /수학: " + this.math);
        System.out.println();
        System.out.print("\n====================\n");

    }
		
}

인스턴스에 대한 메소드에 정의가 가능하다

 

kor에 대한 멤버변수에 this(이것의 인스턴스)를 대입한다.

 

4) 하나의 변수에 우선순위 (지역변수 vs this)

public void printExam() {

    int kor = this.kor; 

        int kor = 10;

        System.out.println("\n단독객체");

        System.out.printf("점수는  ");
        System.out.print(" 국어: " + kor); //이거는 지역변수가 출력됨
        System.out.print(" /영어: " + eng); //이거는 객체의 멤버변수가 출력됨
        System.out.print(" /수학: " + this.math); //이거는 객체의 멤버변수가 출력됨
        System.out.println();
        System.out.print("\n====================\n");

    }

첫번째 :

위와 같은 경우 kor 이 두개인데,

지역변수로 선언한 kor을 별도로 선언해도 오류가 발생하지 않는다.

왜냐하면 kor의 값간에 우선순위 차이가 있기 때문이다.

 

그러하다면 kor에 우선순위는 어떻게 될까?

1순위 : 지역변수 / 2순위 : this이다

 

두번째 : 

만약 지역변수가 없다면 kor에 대해서 명명해줄때 굳이 this를 쓸 필요가없다(즉 this를 지워도 오류가 안뜬다)

왜냐하면 메소드에서 this의 객체를 찾아서 그 객체의 속성(멤버변수)에 kor 이 있는지 찾기때문이다.

 

(2) 객체지향프로그래밍 캡슐화에 의한 특징

(1) 캡슐화 & 정보은닉화(for access modifier) 

1) 문제발생범위

public class Exam {

    int kor1; 
    //이렇게 하는 경우 본 Exam클래스에서만 오류가 바람직하다
    //하지만 메소드가 아니라 함수로하는경우 main함수와관련된
    //함수에까지 오류가 뜨기 때문에 캡슐화로서 역할을 하기가 어렵다.

    public void input() {
        //1. 콘솔 성적 입력

        //				콘솔입력블럭
        Scanner scan = new Scanner(System.in);

        //				화면출력단 --------------------------------
        System.out.println("┌─────────┐"); 
        System.out.println("│                       │");
        System.out.println("│        성적 입력        │");
        System.out.println("│                       │");
        System.out.println("└─────────┘");


	for(int i = 0 ; i < 3 ; i++)  //한문장으로서 블럭잡을필요없음

        do {
            System.out.printf("국어%d:", i + 1);
            kor1 = scan.nextInt();

            if(kor1 < 0 || kor1 > 100 )
                System.out.println("점수를 100까지만 입력해야합니다 \n 다시 입력해주세요");
            }
            while(kor1 < 0 ||kor1 > 100);

        }
    }

 

멤버변수 수정 > 동일 클래스(exam) 내에서만 변수와 관련된 오류가 발생한다.(캡슐화의 이점)

내가 설계하는 구조안에 같이들어가야함 (캡슐화)

만약 일반적인 함수이면 본 클래스 외부에도있는 곳에도 오류가 발생한다. 

결국 캡슐화는 오류여부에 대한 테스트의 범위가 줄어들어 수정가능성이 오를 수 있게된다.

 

2) 멤버변수 캡슐화 - access modifier(접근제어자)

public static void main(String[] args) {

		Exam examl = new Exam();
		
		examl.eng = 30; //바람직하지하는 방법
		//캡슐밖에서는 쓸수없게끔 해야한다
		//캡슐이 그렇게 할수있는 칼자루를 가져야
		 
}

 

examl은 eng 멤버변수에 직접 접근을 할수있다.(캡슐화에 부합X) Exam 클래스의 멤버변수는 public이기 때문이다.

이러한 경우 access modifier(접근제어자)를 이용해서 외부에서 접근하지못하게끔 private를 이용하면된다.

 

(2)초기화와 생성자

int kor = 4; //초기화
kor = 5; //이거를 초기화라고 하지는 않음

kor 상단은 초기화를 했다고 볼수있으나, 아래 kor은 그렇게 보기어렵다

public class CapsuleTest {

	public static void main(String[] args) {

	Exam examl = new Exam();
	examl.init(); 
    }
    
    
public class Exam { 
    public void init() {
			
        kor1 = 30;
        eng = 30;
        math = 30;	
	}
}

초기화는 규칙이 있다. 최초에 선언, 생성할 때에만 값을 준다.

하지만 위 init() 함수는 input()함수 후에도 가능하고, init()를 두번 접근할수 있는 문제점이 두가지있다.

 

결국 이러한 규칙과 문제점 해결을 위해서 존재하는 것이 생성자이다

Exam examl = new Exam(); 에서 이미 초기화하는 함수가 존재한다 '()'이다.

이것을 생성자라고 한다

 

여기서 생상자란 인스턴스를 생성할때 호출되는 인스턴스 초기화 메서드이다.

 

이러한 경우 

public class Exam {
//생성자 선언하기
    public Exam (){ //exam 형식의 객체만 나를 호출할수있다! (한정사)

        kor1 = 100;
        eng = 100;
        math = 100;
        //객체를 새로 생성할때 '만'호출할수있다
        //초기화 의미가 맞다.
    }
}

위와 같이 리턴형이 없기때문에 별도로 쓰지않아도 되고, 매개변수를 아무것도 넣지않는다.

이것이 본래의 초기화 목적에 부합하는 형식이다. (이른바 기본생성자)

 

지금까지 별도의 생성자없이도 초기화가 됐었는데, 번역기가 해주었기 때문이다.

 

<정리>

 

첫번째 객체지향은 말하는것을 그대로하는 것

이제 공부는 표현하는 것을 풀어내는 함수를 정의해야한다.

인스턴스함수 객체함수라고하면서 객체를 통해서 하고 넘겨받는 this를 쓸수있다.

 

두번째 this넘겨받는 함수정의할때 캡슐화로 정의한다 이경우 은닉성을 지켜줘야한다 private이다.

 

세번째 은닉상황을 지켜줘야하는데 초기화를 할때는 객체를 딱 한번만 생성할때만 하고, 한번 호출하고나서 다시하는것은 못하게 하는 정말로 초기화로 하는것을 정의할수있어야한다.

 

 


1. 보충

(1) 객체 해시코드와 가비지 컬렉터

1) 객체를 '식별'하는 정수형 값을 의미한다.

 

2) 가비지컬렉션(garbage collection : gc)

가비지(garbage)란 유효하지않은 메모리를 의미한다.

가비지 colletion은 jvm이 불필요한 메모리를 정리해준다. 여기서 불필요한 메모리는 null로 선언해준다. 

 

 

 

2. 회고 

(1) 함수 / 구조화된프로그래밍 / 그리고 그것의 문제점에 대해서 흐름을 탈수있게 되었다.

 

(2) 캡슐화의 목적과 방식을 이해하게 되었다.

 

(3) 실세계는 존재와 행위로 이루어져있다.

 

(4) this에 대해서 이해할수 있게 되었고, 이와 관련된 우선순위를 이해한다.

 

 

 

 

'배움 __IL > TIL 1기' 카테고리의 다른 글

TIL : 17번째- 221221 [12-3-수]  (0) 2022.12.21
TIL : 16번째- 221220 [12-3-화]  (0) 2022.12.20
TIL : 14번째- 221216 [12-2-금]  (2) 2022.12.16
TIL : 13번째- 221215 [12-2-목]  (0) 2022.12.15
TIL : 12번째- 221214 [12-2-수]  (0) 2022.12.14