Java 객체지향

7. - 함수의 매개변수

구조적 프로그래밍에서 가장중요한것은 무엇일가? 나누는것 나눠진 함수를 호출하는게 중요하다.
매개값으로 전달되는 파라미터를 어떻게 하는지 어렵다.
print(2,3.0f,'a')
->
void print(int x, float y, char c)
매개변수를 어떻게 선언할 것인가?
?x =3 ; ?X=3.5f ; ?x = new int [3] / x ='3' 등등 타입만 정해주면된다.

int[] lotto = new int[3]
print(3, 5.3f, lotto)
->
void print(int a, float b, int[] lotto)
배열은 의미가 잇으니 이름으로 하는게 좋다.
char[][] names = new char[3][10];
??? cnt = print(true, 4.0, names) / ???print(???,???,???) {return2.2}
->
double cnt = print(true, 4.0, names) / double print(boolean a, float b, char[] names){return2.2}

8. 데이터 구조화

지난시간은데이터를 구조화햇다. 구조화라는 것은 그루핑이다. 코드를 잘게 나누엇을때 더큰 그룹을 만든다.
그룹으로 나누서 계층구조를 만들어야한다.
void drawEllipse(int x, int y, int w, int h, int color)일때 원인데 뭐가 원인가?
만약 고객관리 프로그램을 만들때 데이터 고객이름? 고객나이 이런거일가? 아니다 '고객' 자체가 데이터이다.
학생관리 대여관리 대여 학생이런게 데이터이다. 이런것이 개념단위의 데이터, 개체, entity이다.
자바라는 언어도 이런 개념으로 데이터를 제공하지 않으니 펼쳐놓고 이름으로 넣는다.
그럼 자바도 개념단위로 데이터를 주면? 이해하기 편할듯하다.
-> void drawEllipse(Ellipse ellipse) -> void draw(Ellipse ellipse)
자바에서 이런 entity개념화된 데이터를 제공할 수잇다.
다만 그냥 제공하는게 아니라 entity를 쓸수잇게끔 int x int y 이런것들을 엮어서 정의해야한다.



이것을 class로 정의해서 제공하고잇다.
프로그래밍을 할때 데이터를 하나씩 제공하는 것보다

개념화해서 데이터를 제공하는것이 훨씬 코드가 깔끔하고 보기 좋다.

국어성적 관리 프로그램 -> 국어 영어 수학 3개과목을 다룬다면?
int[] engList = new int[3];
int[] mathList = new int[3];
영어 수학도 담을 수있도록 해야한다. 이렇게 되면 입력받는 작업을 여러번 해야한다.
각각 마다 다루면 복잡도도 높아진다. 조금더 세련되게 하려면?
Exam exam;
exam.kor = 30;
exma.eng = 30;
조금더 개념적으로 만들고 거기에 담으면된다.
정의한적이 없어서 컴파일러가 에러를 만드는데 class를 만들수잇다. class는 이런 사용자 원하는 데이터 구조의 형식을 정의하는 것이다.

1.데이터 구조의 정의
2.선언 값형식? 참조형식?
-> Exam exam;은 참조형식이다. null이고 new를 해줘야한다.
그래서 사용할때 exam.kor = 30; 안에잇는 국어방에 데이터를 넣어달라.
이건 class Exam게아님. 여긴 공간이아니라 데이터를 정의하기 위한 키워드일뿐
실존하는 방은 어떻게 만들어야하나?
3.객체생성
exam = new Exam();해줘야한다. 이때서야 정의한 내용을 기반으로 방이 생겨서 담을수있게 된다.
정의하는 모든 것은 참조형식이고 new를 해야지 쓸수잇다는 것을 알아야한다.

9.데이터 구조화 # 2

구조체를 이용한 코드 작성하기
참조형식은 무조건 new로 만든 객체를 대입해줘야한다..
객체지향이든 아니든 무조건 객체를 넣어줘야한다.
Exam exam = new Exam();
int kor; int eng;이런형식을 가져와서 실체화 된것이다.
내부적으로 주소를 저장하지만 개념적으로는 공간이 잇는게아님. 포인터는 주소를 저장하면서 본인도 주소를 가지고 잇엇다.
참조변수는 주소가 없다고 보면되고 객체라는게 존재하면 이름이 필요한데 이름이 해당되는 식별자라고 생각하면된다.
참조변수는 객체를 식별하는 이름이라고 생각하면된다. 참조된게잇으니 객체의 공간에 값을 넣을 수잇게되는 것이다.

exam.kor = 30;
exam.eng = 30;
exam.math = 30;

중요한 것은 참조형태로만 사용이 가능하다. 함수로 전달해도 결국 참조를 하는것이다.

inputExam(exam); ->input(exam);이미 뭘전달하는지 알기때문에 그냥 이렇게 작성하면된다.

성적출력

private static void print(Exam exam) {
    System.out.println("┌──────────────────────────┐");
    System.out.println("│          성적출력        │");
    System.out.println("└──────────────────────────┘");
    System.out.println();

    int kor = exam.kor ;
    int eng = exam.eng;
    int math = exam.math;

    int total = kor + eng + math;
    float avg = total / 3.0f;

    System.out.printf("국어: %3d\n", kor);
    System.out.printf("영어: %3d\n", eng);
    System.out.printf("수학: %3d\n", math);

    System.out.printf("총점 : %3d\n", total);
    System.out.printf("평균 : %6.2f\n", avg);
    System.out.println("────────────────────────");
}

exam.kor; 들을 반복적으로 사용하니까 임시변수에 담아서 사용하자.

성적입력

private static void input(Exam exam) {
    Scanner sc = new Scanner(System.in);

    System.out.println("┌──────────────────────────┐");
    System.out.println("│          성적입력        │");
    System.out.println("└──────────────────────────┘");
    System.out.println();

    int kor, eng, math;

    do {
        System.out.printf("국어: ");
        kor = sc.nextInt();

        if (kor < 0 || 100 < kor) {
            System.out.println("국어성적은 0~100까지의 범위만 입력이 가능합니다.");
        }
    } while (kor < 0 || 100 < kor);

    do {
        System.out.printf("영어: ");
        eng = sc.nextInt();

        if (eng < 0 || 100 < eng) {
            System.out.println("영어성적은 0~100까지의 범위만 입력이 가능합니다.");
        }
    } while (eng < 0 || 100 < eng);

    do {
        System.out.printf("수학: ");
        math = sc.nextInt();

        if (math < 0 || 100 < math) {
            System.out.println("수학성적은 0~100까지의 범위만 입력이 가능합니다.");
        }
    } while (math < 0 || 100 < math);

    exam.kor = kor;
    exam.eng = eng;
    exam.math = math;

}

구조체 형태로 사용하니 다양한 값을 전달받아야해도 깔끔하게 코드가 짜인다. 힌트를 가져올수잇어서 함수이름도 간편해진다.

10. 구조체 배열 이용하기

데이터를 구조화한것이 구조체 현재 사용하고 데ㅐ이터는 데이터만 구조화하는 구조체이다.
배열을 이용해 여러개의 성적을 입력받기 위한 구조체 배열
Exam exam = new Exam();
->
Exam[] exams = new Exams[3];할 수있다.
exams[0].kor = 30;
그런데 주의해야한다. 전자는 실제 Exam이라는 공간이 만들어진것이다.
후자는 Exam형식의 배열이 만들어진것이라 exams[0].kor = 30;이 안된다.
참조변수 3개짜리를 만든거임
이게 오류가 안나려면
exams[0] = new Exam(); 0번째 이름표에다가 객체를 심어줘야한다!!!!!
실제 객체를 참조시켜줘야한다.
배열을 만들면 그냥 객체 배열이아닌 객체 참조배열이다. 국어영어수학을 만들려면
공간에 객체를 만들어줘야한다. 배열은 이름포 3개만 준비하는 것이다.

11. 가변 길이 배열

배열 입력 받을때 점진적으로 입력하는게 귀찮다 그걸 해결해보자.
원래 배열은 가변적이지 않고 고정적이다.
미리정해둬야한다. 그런데 프로그램을 만든다고 할때 max를 미리 정해놔라? 너무 어렵다.
최소를 잡고 손님이 오면올수록 추가를 만들면된다.
저절로 늘어나는 방법은 없다. 늘어나게하려면 더크게 만들고 이주시켜야한다.

하나만 입력받고 빠져나오고 갯수를 입력받아 또받으면 다음 것을 받으면된다.

current로 값을 쌓아서 입력이 될때마다 current값을 증가시켜 exams[current] = exam;넣는다.
이러면 가변적인 배열을 할 수 있게된다.
출력은 3번을 다 출력하는게 아니라 배열중 current만큼만 출력하면된다

12. 가변 길이를 위한 구조체 생성

문제가잇엇는데 입력에서 currnet++;를 해봣자 그 안의 지역변수에서 늘어나는거라
print에서 전달받앗을때 0만 계속 전달받아서 증가된 값을 받지 못한다.
이걸 어떻게 해야하나?
c나 c++은 이것의 주소또한 가져다 쓸수잇엇지만 자바는 이를 막아놓앗다.

이걸 더 큰 단위로 묶으면된다.


list로 한번에 전달 하자.

13. 가변 길이 배열 구현하기

더큰 배열을 만들어서 넣으면 된다. -> 컬렉션 이용하면 필요없는 부분같은데?
가변적으로 데이터를 수집하기 위해 배열을 이용하려면 어떻게 해야할까?
current로 커서를 만들어서 점점 앞으로 갓다.
충분히 큰 크기를 마련하는 방법 : 1000-초기크기
다쓸때 한개씩 늘려가는게 낫다.
[] current + capacity + amount
1.amount개 확장한 새로운 배열 temp를 생성한다.
2.list에 있는 데이터를 temp배열로 옮긴다.
3.temp가 참조하는 객체를 list가 참조하게 한다.
4.현재 capacity의 값을 +10증가시킨다.

Exam[] exams = list.exams;
    int size = list.current;

    if (exams.length == size) {
        //1.크기가 5개정도 더 큰 새로운 배열생성
        Exam[] temp = new Exam[size + 5];
        //2.값이주
        for (int i = 0; i < size; i++) {
            temp[i] = exams[i];
        }
        //3.list.exams가 새로만든 temp 배열참조 
        list.exams = temp;
}

14. 함수 오버로딩(overloading)

우리가 최종적으로 하려는건 객체지향임. 이렇게 짜면 유지보수할때 문제가 발생함.
이걸해도되고 안해도된다. 안하면 좀 불편해짐.
printList(list) 로 출력햇다.
그런데 3개만 출력하고싶다? printList(list, 3)하면되는데
그래서 오버로딩를 사용하면된다.
기존의 함수를 또 만들면된다. 기능이 같은데 옵션이 다르고 제약사항이 들어가는 것임.
두번다 구현할 필요가 없다. 작성하지 않느게 바람직하다? 그건아님. 오버하는 이유ㅜ가잇다.
사용하는 사람입장에서는 다출력하는게 더 많이 사용할 것임. 굳이 한정된 것을 위해 인자를 또 넣게하면 불편해짐.

구현하는 입장에선 불편하지만 사용자 입장에서는 3개다 구현되서 필요에따라 골라쓰게 해주는게 좋다.
구현하는쪽에서는 가장 마지막거만 구현하고 나머지는 재호출하면 된다.

주의할 사항이 잇음 인자에 따라 기능이 차이가 나지만 이름이 같으면 헷갈릴 수잇다.
집중화를 해야한다. 둘중 인자가 많은 거를 선택한다.
인자가 없는쪽은 구현하지 않는다. 오버로드된 함수를 재호출하면된다.

15. 코드 실행과 함수 호출 스택

https://youtu.be/dBRU_-eLvpU --> 영상
코드를 작성하는데 이게 실행될때 어떻게 실행되고 메모리 사용관계는 어떻게 되나?
heap입석과 stack예약석


stack은 아래부터 쌓고 사용하면 위에 사용한게 먼저 없어짐.
main도 사용을 끝내면 메모리에서 없어짐.
heap영역은 참조가 사라져도 메모리에서 안사라짐. 그래서 자바는 참조되지않는게 잇으면 주기적으로 찾아서 삭제해줌
과거에선 이런 메모리 누수가 잇엇다.

1. 객체지향 프로그래밍의 시작 캡슐화

모호하다.
객체 지향이란? 실세계의 일들을 객체로 사용해서 모델링하는 것


무엇을 클래스로 작성할지 모르겟다.

프로그래이란 절차가 전부이다.
프로그램 -> 방법1 ->어떤 문제가 잇엇으며 새로운 방식이 필요햇을 것이다.-> 방법2
절차적인 프로그래밍 + 구조적인 프로그래밍 + 문제 + 객체지향 프로그래밍
왜 사용해하는지 모르겟다.

1.1 캡슐화

https://youtu.be/yGBmRdgc1Ic
프로그램이 너무길어서 잘라서 만들엇는데 그게 구조화된 프로그램이엇다.
잘게 쪼개진 프로그램으로 만들어진다. 그런데 점점길어지면 이 함수가 너 무 많아짐 이런것들을 어떻게 정리하나?
어떤 기준으로 수납?
기능에 따라서 분리? / 데이터에 따라 분리
-> 데이터에따라 분리하는게 맞다.
why? 구조화된 데이터를 사용하는 함수 모듈의 독립성을 침해하는 문제를 해결할 수 잇기때문에
함수는 외부의 수정에 절대 영향을 받으면 안되기때문이다. 함수는 데이터로 돌아가는데 독립된 녀석이어야한다.

구조화된 데이터를 사용하면 구조화된데이터의 속성이 변화하면 문제가 발생한다.
해결방법1.절대변수명을 바꾸지않는다. 2.바꾸면 모든 코드를 바꿔서 바꾼다.
둘다 좋지않음. 고치면 같이 바뀌도록 모아놓는다.
범위가 한정되서 수정하는게 쉬워진다.

따라서 캡술화하면 데이터 구조에 따른코드의 수정범위를 캡슐범위로 한정할 수 있다.
이런것들을 모으다 보니 모든 프로그램이 캡슐이 되엇다.

2. 함수들을 캡슐화하기

캡슐화 : 데이터 구조와 함수를 하나의 영역에 함께 모아 놓는 작업

다른 클래스의 함수를 사용하려면 밝히고 사용해야한다.

//초기화 함수
ExamList.init(list); 

case 1:
    ExamList.inputList(list);
    break;
case 2:
    ExamList.printList(list);
    break;

public class ExamList {

    Exam[] exams;
    int current;

    static void printList(ExamList list) {
        printList(list, list.current);
    }

    static void printList(ExamList list, int size) {
        ...
    }

    static void inputList(ExamList list) {
        ...
    }


    public static void init(ExamList list) {
        list.exams = new Exam[3];
        list.current = 0;

    }

3. 인스턴스(Instance) 메소드

객체와 함수의 관계 문제를 해결하는 방법으로 나왓던걸 알려준다.
절차를 작성하다보니 문제가 발생함. 함수를 사용하는것에서 불편한게 생김.
ExamList list = new ExamList();
ExamList.inputList(list); 구조화된걸 실체화해서 사용해야한다.
문제는 이객체가 잘안보인다. 행위에 대한 주체가 잘보이지 않는다.
list를 이용한 처리 실제 주체가 안보인다.
->list.inputList();
list를 이용한 입력 list를 이용한 출력 등등

list.하는게 훨씬편하다. 함수가 사용할 수있도록 넘겨받게 파라미터를 하느게아니라 기본적으로 전달받게 하자.
캡슐한테 list객체를 이용해서 하려면 알아서 객체가 담아주게 해야한다.
list야 입력해, list야 출력해라고 해버리게 해줘야한다. 책임을 전가해야한다.
구조환된게 캡슐화되면 역할도 부여해서 주체가되서 사용하게 해야한다.

객체가 눈에띄고 객체가 하는것으로 만드는 것임.

4. 인스턴스(Instance) 메소드 구현하기

매개변수, static을 없애야한다.
함수랑 메소드와의 차이?
같은 말인데 개념이 달라졋다. 메소드는 명령이다. 서비스를 위한 함수 = 메소드인 것이다.
다른 언어에서는 함수 / 메소드라고 한다. 자바에서는 static(정적)메소드 / 인스턴스메소드라고 한다.
정적메소드는 원래 형태의 함수라고 보면된다. static일경우에는 파라미터가 잇어야햇는데
인스턴스일때는 똑같은 로직이지만 넘겨받은거는 어떻게 사용하나? this로 하면된다.

책임을 가지게 만드는것임. 의인화 객체지향
그런데 this는 무조건 받게 되서 지워도된다. 그러면 지우느게 맞나 쓰는게 맞나? 지워도되면 지우는게 좋다.
식별해야되서 못지울땐 안지우면된다.

'기초단계 > JAVA' 카테고리의 다른 글

2023.02.14 Java 복습  (0) 2023.02.14
2023.02.13 Java 복습  (0) 2023.02.13
2023.02.11 Java 복습  (0) 2023.02.12
2023.02.10 Java 복습  (0) 2023.02.10
2023.02.09 Java 복습3 시작  (0) 2023.02.09

+ Recent posts