인프런 커뮤니티 질문&답변

David님의 프로필 이미지
David

작성한 질문수

나도코딩의 자바 기본편 - 풀코스 (20시간)

생성자 안에 메소드...?!

해결된 질문

작성

·

950

0

안녕하세요, 선생님...ㅎ 갑작스럽게 생각난 질문인데요...ㅎ 제가 예시로 아래처럼 클래스를 만들어 봤는데, 혹시 상속받은 클래스의 super(); 생성자 안에 이렇게 메소드도 넣을 수 있나요? 자바를 공부하면서 지금 여러 소스 코드들을 보고 있는데, 어느 소스코드는 super(); 생성자 안에 메소드를 집어 넣은 경우가 있더라구요?! 만약에 이렇게 만들 수 있다면, 언제 어느 때 가능할까요?

클래스는 정말 제가 생각나는대로 적어서 컴파일 에러 같은 건 생각하지 않았습니다. 부디 너그럽게 봐주셨음 합니다...ㅎ

class Kid extends SomethingAwesome {
    Kid(int age) {
       super(comment(age)); // super() 생성자 안에 comment메소드 삽입
    }
   
    public String comment(int age) {
       String saySometing = "";
       if (age > 3 && age < 7) {
          saySomething += "엄마, 과자 사줘!";
       } else if (age >= 7 && age < 11) {
          saySomething += "엄마, 이젠 로보트 사줘!";
       }
       return saySomething;
    }
    
    public static void main(String[] args) {...}
    // 메인 메소드 실행
}

또한 일반적인 생성자 (Constructor)를 만들 때도, 생성자 안에 전달 값외에도 메소드를 넣을 수 있는가요? 이것도 마찬가지로 위에 예시로 코드를 적은 것 처럼 제 나름대로...ㅎ 써봤습니다...ㅎ 위의 예시 처럼 정말로 생성자 안에 메소드를 넣는게 가능한지 궁금해서 약간 무리수를 두면서(?) 코드를 적어봤습니다..ㅎ 이것도 너그럽게 봐주세요...ㅎ 감사합니다 : )

class ThankYouNote
{
   // 제가 생각해도 좀 많이 이상하지만,
   // 메소드를 이렇게 선언해서 do = thanks();
   // this.do = do; 이렇게는 많이 무리수죠? ㅠㅠ
   // 저렇게 위 클래스 처럼 super 생성자 안에 메소드를 넣는건 처음봐요 ㅠㅠ

   ThankYouNote() {
       thanks();
       // this(thanks()); 
       // 너무 많이 무리수 인듯하지만 일단 적어봤습니다...ㅠㅜ 
   }

   public void thanks() {
      System.out.println("나도코딩 선생님, 감사합니다. :)");
   }

   public static void main(String[] args){ ... }
   // 메인 메소드 실행
}

답변 2

1

나도코딩님의 프로필 이미지
나도코딩
지식공유자

보통 생성자에 들어가는 값들은 직접 입력하거나 외부의 다른 클래스 객체의 메소드로부터 반환된 값을 사용합니다. 자기 자신의 메소드로부터 반환된 값을 생성자에 넣는 경우는 그리 많지 않은 것 같아요. 그래서 "부모 클래스에서 상속받은 자식 클래스 생성자 super(); 에서는 필요한 경우에 static 메소드에서 반환된 값을 이용할 수도 있다" 로 정리해주시는 것이 좋겠습니다. 😊

1

나도코딩님의 프로필 이미지
나도코딩
지식공유자

안녕하세요?
먼저 다른 예제로 접근해보겠습니다. 아래 코드를 실행했을 때 결과가 어떻게 될까요?

public static void main(String[] args) {
    System.out.println(1);
    System.out.println(2);
    System.out.println("사과");
    System.out.println("바나나");
}

결과는 이렇습니다.

1
2
사과
바나나

여기에 아래 메소드들을 추가해볼게요.

public static int one() {
    return 1;
}

public static int two() {
    return 2;
}

public static String apple() {
    return "사과";
}

public static String banana() {
    return "바나나";
}

그런 다음에 main() 메소드도 다음과 같이 바꿔보겠습니다. 이번에는 실행 결과가 어떻게 될까요?

public static void main(String[] args) {
    System.out.println(one());
    System.out.println(two());
    System.out.println(apple());
    System.out.println(banana());
}

네, 실행 결과는 동일합니다.

1
2
사과
바나나

이게 무슨 의미냐면, System.out.println( ); 의 괄호 속에 들어가는 값에는 어떤 값을 넣을 수도 있고 변수를 넣을 수도 있고 메소드를 넣을 수도 있습니다. 값이라면 그 값을 직접 출력하고, 변수라면 그 변수에 저장된(또는 참조하는) 값을 출력하고, 메소드라면 그 메소드에서 반환해주는 값을 출력하게 됩니다. System.out.println( ); 입장에서는 괄호 속으로 전달받는 값을 그냥 출력해주기만 하면 되는 것이며, 이 값이 그냥 값인지, 변수에 저장된 값인지, 메소드로부터 반환된 값인지는 몰라도 됩니다. 우리가 운영하는 식당에 어떤 손님이 오셨는데 이 분이 걸어왔는지, 차를 타고 왔는지, 버스를 타고 왔는지는 아무런 상관이 없습니다. 그저 우리 식당에 왔다는 것이 중요한 거죠.

super(); 도 똑같습니다. super( ); 안에는 부모 클래스의 생성자에서 필요로 하는 데이터를 넣어주면 됩니다. 만약 정수형 자료를 원한다면 1, 2 와 같은 값을, 문자열 자료를 원한다면 "사과", "바나나" 와 같은 값을 넣어주면 됩니다.

super(1);

super(2);

super("사과");

super("바나나");

그런데 이렇게 값을 바로 넣지 않고 다음과 같이 메소드에서 반환해주는 값을 넣도록 해도 동일합니다.

super(one());

super(two());

super(apple());

super(banana());

부모 클래스의 생성자에서는 그저 이 메소드들이 반환해주는 값을 그대로 활용하는 것 뿐이죠. 그래서 엄밀히 말하면 "생성자 안에 메소드를 넣는다" 라고 이해하시기보다는 "생성자 안에 어떤 값을 넣는다. 그런데 그 값은 메소드로부터 반환된 값이다" 라고 이해하시면 좋습니다.

단, 이때 one(), two(), apple(), banana() 메소드들은 static 으로 정의가 되어있어야만 사용이 가능합니다. non-static 으로 정의된 메소드인 경우 생성자에서 super(); 문장을 실행하는 시점에서는 아직 사용이 불가합니다. static 으로 정의된 변수나 메소드는 해당 클래스로부터 객체가 만들어지지 않아도 사용이 가능하다는 점을 기억해주시면 좋겠습니다.

그래서 다음 코드는 에러가 발생합니다.

class A
{
    public String s;

    public A(String s) {
        this.s = s;
    }
}

class B extends A {
    public String str;

    B(String str) {
        super(comment()); // 에러 발생
        this.str = str;
    }

    public String comment() {
        return "좋은 질문이에요";
    }
}

하지만 comment() 메소드를 다음과 같이 static 으로 바꿔주면 에러는 사라집니다.

    public string String comment() {
        return "좋은 질문이에요";
    }

일반적인 생성자를 만들 때도 이와 동일합니다. 작성해주신 코드를 조금 바꿔봤어요.

class ThankYouNote
{
    public String s;

    ThankYouNote(String s) {
        this.s = s;
    }

    ThankYouNote() {
        this(thanks());
    }

    public String thanks() {
        return "열심히 공부해주셔서 감사합니다";
    }
}

기본 생성자와 사용자 정의 생성자를 따로 두고 기본 생성자에서 사용자 정의 생성자를 호출하며 thanks() 메소드를 사용하는 경우입니다. 그리고 thanks() 메소드는 반환값으로 문자열을 반환합니다. 객체 생성은 별도의 클래스 내의 main() 메소드에서 진행하면 되구요.

위와 같이 코드를 적게 되면 오류가 발생합니다. 하지만 앞의 설명과 동일하게 thanks() 메소드를 static 으로 정의하게 되면 정상 동작하게 됩니다.

    public static String thanks() {
        return "열심히 공부해주셔서 감사합니다";
    }

public 으로 정의된 클래스의 main() 메소드에서 이렇게 객체 생성 및 s 변수의 값을 출력해봤어요.

public static void main(String[] args) {
    ThankYouNote thankYou = new ThankYouNote();
    System.out.println(thankYou.s);
}

실행 결과는 이렇습니다.

열심히 공부해주셔서 감사합니다

학습에 도움되시길 바라겠습니다 😊
감사합니다.

David님의 프로필 이미지
David
질문자

안녕하세요, 나도코딩 선생님...ㅎ 답변 글 감사합니다...ㅎ 선생님의 답변 글이 너무 도움되서 답변 알림 보자마자 후다닥 읽었네요...ㅎ 프로그래밍 공부할 때마다 너무나도 큰 힘이 됩니다...ㅎ

그 올려주신 답변글에서 생성자 안에 메소드를 집어넣는게 아니라, 생성자에서는 메소드를 통해 만들어진 반환 값을 이용한다는 것은 확실하게 이해했는데, (정확히 "생성자 안에 어떤 값을 넣는다. 그런데 그 값은 메소드로부터 반환된 값이다" - 이 부분이요.)

부모 클래스에서 상속받은 자식 클래스 생성자 super();에서는 non-static 메소드의 반환 값들이 아닌 static 메소드(들)에서만 반환된 값(들)을 이용한다라고 규칙을 이해하면 될까요?

David님의 프로필 이미지
David

작성한 질문수

질문하기