Loading...

JAVA / / 2022. 1. 13. 15:09

자바 14강. 생성자

반응형

[복습]

 

객체지향 1원칙

(OOP를 잘 짜는 방법)

상태는 행위에 의해 변경된다.

 

오브젝트 = 실존할 가능성이 있는 것

클래스 = 이상적인 설계도(선언만 함)

인스턴스 = 실재하는 것

 

메서드(함수)

= 함수가 실행되면 스택이 열린다.(메서드마다)

 

class A {               

    int num = 15;

함수명 ( ) {

           int num = 10;

                        sysout("결과 : " + num);

}           

}                  

 

변수는 항상 자기와 가까운 것부터 찾는다.

// 결과 : 10


프로그램을 작성할 때 홀로 작동하는 객체는 거의 유용하지 않다.

객체는 메시지(message)를 통해 다른 객체와 통신하고 서로 상호 작용한다.

이때 메시지는 메서드를 호출하는 행위를 말한다.

 

메시지에는 추가적인 정보들이 필요할 때도 있다.

이런 정보들은 메시지의 매개변수(parameter)의 형태로 전달된다.

 

지난 계산기 프로그램을 예로 들어

multi 메서드의 매개변수는 int타입의 a1과 a2이고,

이 메서드를 호출하는 21번 라인이 메시지이다.

호출할 때 넣어주는 값은 argument(인수)라고 한다.

 


 

클래스를 붕어빵 틀처럼

새 객체들을 찍어낼 수 있다고 했었다.

 

package ex07;

class 질럿 {
    String name = "질럿";
    int hp = 100;
    int attack = 10; 
}

public class OOPEx05 {
    public static void main(String[] args) {
        질럿 z1 = new 질럿();
        질럿 z2 = new 질럿();
        질럿 z3 = new 질럿(); // heap에 질럿 3마리 떴음
        
        // 행위만이 상태를 변경한다는 사실 배제한 예제 !!
        z1.hp = 50;
        z2.hp = 70;
        z3.hp = 1;

        System.out.println("질럿1의 hp는 " + z1.hp);
        System.out.println("질럿2의 hp는 " + z2.hp);
        System.out.println("질럿3의 hp는 " + z3.hp);
    }
}

클래스를 만들고 클래스 내부 변수를 선언한 뒤 초기화까지 했을 때

위 코드처럼 상태를 직접 변경할 수가 없기 때문에

똑같은 변수만 계속해서 생성할 수밖에 없게 된다.

 

이 때문에 클래스의 내부 변수는 초기화를 하지 않고 선언만 해줘야 한다.

 

package ex07;

/**
 * 클래스 문법
 * 클래스 내부 변수(상태)는 선언만 한다.
 * 
 */

class 사람 {
    String name;
    int height;
    int weight;
}

public class OOPEx06 {
    public static void main(String[] args) {
        사람 s1 = new 사람();
        s1.name = "홍길동";
        s1.height = 50;
        s1.weight = 5;
        System.out.println(s1.name + " 키 : " + s1.height + " 몸무게 : " + s1.weight);

        사람 s2 = new 사람();
        s2.name = "장보고";
        s2.height = 100;
        s2.weight = 8;
        System.out.println(s2.name + " 키 : " + s2.height + " 몸무게 : " + s2.weight);

        사람 s3 = new 사람();
        s3.name = "임꺽정";
        s3.height = 70;
        s3.weight = 10;
        System.out.println(s3.name + " 키 : " + s3.height + " 몸무게 : " + s3.weight);
    }
}

클래스 내부 변수에 선언만 하게 되면

원하는 대로 초기화해줄 수 있다.

근데 위 코드처럼 프로그래밍을 하면

일일이 초기화해주기 귀찮으니까 우리는 생성자라는 것을 사용할 것이다.

 

생성자(Constructor)

 

package ex07;

class Person {
    // 변수 선언만 해주기
    String name;
    int height;
    int weight;

    // 디폴트 생성자
    Person() {
        System.out.println("사람이 생성되었습니다");
    }
}

public class OOPEx07 {
    public static void main(String[] args) {
        Person s1 = new Person();
    }
}

 

Person 클래스 안에 메서드같이 생긴 Person( )이 보인다.

메서드라고 하기에는 return 타입이 적혀있지 않다.

저것이 생성자이다.

 

생성자는 객체의 초기화를 위해 필요하다.

 

미리 상태를 초기화해놓으면 항상 똑같은 객체가 나오기 때문에

매번 다른 객체를 만들기 위해 상태는 선언만 해두고

생성자를 통해 초기화해준다.

 

생성자는 메서드 형식과 똑같은 구조인데,

생성자 이름은 클래스 이름과 동일해야 한다.

클래스명 ( ) { }

 

17번 문장에 Person s1 = new Person ( );

사람 클래스에서 컨트롤 클릭해보면

위에 Person( ) 생성자 부분으로 커서가 옮겨간다.

 

생성자를 호출하는 문장이었던 것이다.

하지만 우리는 여태 클래스를 만들어오면서

생성자를 직접 만든 기억이 없을 것이다.

 

생성자는 내가 직접 만들지 않으면

컴파일러에서 항상 디폴트 생성자가 자동으로 만들어졌기 때문이다.

(생략해도 된다는 말!)

 

생성자가 메서드와 구조는 같지만 메서드는 아니다.

메서드와 달리 return 타입이 없다.

 

하지만 메서드와 같이 호출받았을 때 stack과 Queue가 생긴다.

내부적으로 돌아가는 원리도 메서드와 동일하다.

 

생성자를 사용하는 방법을 알아보자.

 

package ex07;

class Person2 {
    String name;
    int height;
    int weight;

    Person2(String d1, int d2, int d3) {
        // 생성자가 종료되면 stack 메모리에서 날아가니까 heap으로 옮겨줌
        name = d1;
        height = d2;
        weight = d3;
    }
}

public class OOPEx08 {
    public static void main(String[] args) {
        // 객체 만드는 시점에 초기화 가능
        Person2 s1 = new Person2("홍길동", 170, 70);
        Person2 s2 = new Person2("임꺽정", 150, 200);

        System.out.println(s1.name);
        System.out.println(s2.name);
    }
}

 

생성자의 매개변수에는

new를 사용해 heap 공간을 할당할 때 인수를 통해 값을 지정해준다.

 

생성자도 메서드와 마찬가지로 stack과 Queue가 생긴다고 했는데

또한 내부의 Queue가 다 실행되고 stacak이 종료되면

데이터들이 날아가기 때문에

heap공간의 상태 변수로 옮겨준다.

 

그림으로 생성자 실행과정을 알아보자.

 

 

이때 매개변수들의 이름이 d1, d2, d3인데

실제로 프로그래밍을 할 때 인수에 넣을 값 이름이 d1, d2, d3이면

어떤 값을 넣어주어야 할지 모를 것이다.

 

이름을 친절하게 바꿔주자.

 

package ex07;

class Person3 {
    String name;
    int height;
    int weight;

    Person3(String name, int height, int weight) {
        name = name;
        height = height;
        weight = weight;
    }
}

public class OOPEx09 {
    public static void main(String[] args) {
        Person3 s1 = new Person3("홍길동", 170, 70);
        Person3 s2 = new Person3("임꺽정", 150, 200);

        System.out.println(s1.name);
        System.out.println(s2.name);
    }
}

그런데 상태 변수와 매개 변수의 이름이 같아져서

툴에 경고 줄이 생길 것이다.

 

변수는 원래 가장 가까운 곳에 선언되어있는 곳을 찾아가서

이 name 변수들이 똑같이 생성자의 매개변수를 가리키고 있기 때문이다.

 

생성자의 변수와 heap 영역에 있는 변수의 구분을 위해 우리는

this를 사용할 것이다.

 

변수 앞에 this. 을 붙여서 사용해준다.

 

this.name은 가까이에 있는 변수가 아닌 heap영역에 있는 변수들을 가리키게 되는 것이다.

 

이때 생성자의 name은 지역변수(lacal variable),

heap 공간의 name은 전역 변수(멤버 변수)라고 한다.

 

스택에서 만들어진 변수는 모두 지역변수이다.

잠깐 메모리에 떴다가 사라지는 변수라서 지역변수라고 한다.

 

지역변수냐 전역 변수(= 멤버 변수)냐는

heap에 들어가 있냐 stack에 들어가 있냐의 차이이다.

 

package ex07;

class Person3 {
    String name;
    int height;
    int weight;

    Person3(String name, int height, int weight) {
        this.name = name;
        this.height = height;
        this.weight = weight;
    }
}

public class OOPEx09 {
    public static void main(String[] args) {
        Person3 s1 = new Person3("홍길동", 170, 70);
        Person3 s2 = new Person3("임꺽정", 150, 200);

        System.out.println(s1.name);
        System.out.println(s2.name);
    }
}

가장 아름다운 코드!

 

 

*

 

클래스 내부의 변수를 호칭하는 이름의 종류가 많다.

 

메모리 관점 : heap 변수(무조건 heap에만 뜰 수 있기 때문에)

객체지향 관점 : 상태 변수

컴퓨터 프로그래밍 관점 : 필드 변수(가 클래스 안에 있기 때문에 멤버 변수라고도 함)

외국인 관점 : 속성(property)

 

우리는 속성이라고 부르기로 통일하자!

 

 

 

 

 

[출처]

 

https://cafe.naver.com/metacoding

 

메타코딩 : 네이버 카페

코린이들의 궁금증

cafe.naver.com

메타 코딩 유튜브

https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9

 

메타코딩

문의사항 : getinthere@naver.com 인스타그램 : https://www.instagram.com/meta4pm 깃헙 : https://github.com/codingspecialist 유료강좌 : https://www.easyupclass.com

www.youtube.com

 

반응형