생성자 (Constrtuctor)

  • 메소드(함수)의 일종
  • Class명과 같은 이름의 함수
  • 클래스를 초기화 할 때 쓰임 (예시: int sum = 0)

생성자의 특징

  • 다시 호출할 수 없다 (여러 번 반복해서 실행 불가)
  • Return 값이 없다
  • Over Load가 가능하다
  • Class를 생성할 때 자동 호출된다
  • 클래스를 초기화 할 때

참고 : Destructor

  • 소멸자
  • 현재는 사용 안 함 (가비지 컬렉터가 이어 받음)
  • C++에는 아직 있는 것으로 앎

생성자 코드 예시 1 - 기본 형식

// 메인함수
public class Sample {
    public static void main(String[] args) {
        MyClass cls = new MyClass();    // 여기에서 constructor가 호출됨, 이것이 매개변수임.
    }
}
// 클래스
public class MyClass4 {
    private int number;
    private String name;
    private double height;
    private String birth;

    // 기본 생성자
    public MyClass4() {
        System.out.println("MyClass4    MyClass4()");
    }
}

실행 결과

 

생성자 코드 예시 2 - 초기값을 넣어주는 생성자

반드시 모든 멤버 변수를 초기화 해줄 필요는 없다. (0개 이상)

public class MyClass4 {
    private int number;
    private String name;
    private double height;
    private String birth;
    
    public MyClass4(int number, String name, double height, String birth) {
        this.number = number;
        this.name = name;
        this.height = height;
        this.birth = birth;
    }
}
// 메인 함수에서 객체 생성
MyClass4 cls = new MyClass4(10, "김정은", "159", "2001/01/01");

 

생성자 코드 예시 3 - 매개변수가 없는 생성자 + this + 초기화 생성자

물론 이렇게는 잘 쓰지 않는다. (복잡하다)

초기화가 필요한 경우라면, init() 메소드를 따로 만드는 것이 일반적임.

// 기본 생성자
public MyClass4() {
    this(1000, "김성일", 172.5, "03/05/2019");
    System.out.println("MyClass4    MyClass4()");
}

// this로 호출되는 생성자
public MyClass4(int number, String name, double height, String birth) {
    this.number = number;
    this.name = name;
    this.height = height;
    this.birth = birth;
}

 

참고: IDE 단축키 Alt + Insert

에디터 창에서 누르면 메서드를 바로 생성할 수 있다. 초기화할 멤버 변수를 선택해서 생성자를 만들 수도 있고, 게터와 세터를 만들 때 특히 편하다. toString() 오버라이드 메서드도 이걸로 만들면 빠르다.

 

@Override
public String toString() {
    return "MyClass4{" +
            "number=" + number +
            ", name='" + name + '\'' +
            ", height=" + height +
            '}';
}

 

이런 식으로 작성된다

Over Load

  • (함수의) 이름만 같고, 매개변수의 자료형이나 개수가 다른 함수 == 동명이인
  • 왜 오버로딩을 하는가? -> 기능의 세분화
  • 같은 기능을 수행하지만 입력 받는 매개변수가 달라야 할 경우

오버로딩 함수의 예시 : Integer.parseInt()

    String str = "123";
    int num10 = Integer.parseInt(str);    // 문자열을 10진수로

    str = "1010";
    num10 = Integer.parseInt(str, 2)    // 이진수를 10진수로

코드 예시 1 : 매개변수의 자료형이 다른 경우

    void method(char c) {
        System.out.println("MyClass3 method(char c)");
    }

    void method(int i) {
        System.out.println("MyClass3 method(int i)");
    }

// 호출부
    cls.method('A');
    cls.method(123);

코드 예시 2 : 매개변수의 입력 받는 순서가 다른 경우

    void method(char c, int i) {
        System.out.println("MyClass3 method(char c, int i)");
    }

    void method(int i, char c) {
        System.out.println("MyClass3 method(int i, char c)");
    }

// 호출부
    cls.method('B', 123);
    cls.method(123, 'C');

가변인수

  • 0개 이상의 매개변수를 전달 가능함
  • ... 으로 형식 처리
  • 가변 인자는 내부적으로 배열로 처리됨
    int count(int...number) {
        int count = 0;
        for (int i=0; i<number.length; i++) {
            count = count + number[i];
        }
        return count;
    }

    // 호출부
    System.out.println(cls.count(1, 2, 3));
    System.out.println(cls.count(10,9));
    System.out.println(cls.count());

 

실행결과

 

this : reference (참조)
       포인터
       자기 자신을 가리키는 포인터
       클래스의 어디에서나 접근이 가능
       메소드의 0번째 매개변수 설정되어 있음

MyClass mycls = new MyClass();
        stack       heap

 

class MyClass2 {
    public void setNumber(int number) {
        this.number = number;       // 같은 이름을 적게 되면 구분 필요
        // 멤버 변수    가변수(매개변수)
    }
}

은닉성(=캡슐화)
외부 (클래스밖)와의 접근을 차단 또는 허용하도록 제어
접근 지정자를 사용하여 변수, 메소드의 접근을 차단/허용할 수 있다

접근지정자
private(개인적인) : 외부 접근 차단
public (대중적인) : 어디든지 접근이 가능
protected (보호) : 상속 관련 / 자식클래스에서 접근 허용 / 외부 접근 차단

 

public class MyClass {
    // 내부에서 멤버 변수와 멤버 함수 간의 접근은 ok
    // (멤버) 변수 -> 거의 private 99%
    private int number;
    public String name;     // 은닉성 위배
    protected double height;

    // (멤버) 함수 -> 거의 public 100%. 클래스 내부에서만 쓸 때는 private
    private void function() {
        System.out.println("MyClass function()");
    }
    public void method() { // default값은 외부 접근 불가
        System.out.println("MyClass method()");
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int i) {
        number = i;
    }
}

 

 

 

1. 개념적 접근

  • 절차 지향 프로그래밍: 프로그램을 일련의 절차나 함수로 구성합니다. 데이터와 기능이 분리되어 있으며, 주로 함수 호출을 통해 흐름을 제어합니다. 예를 들어, C 언어가 대표적입니다.
  • 객체 지향 프로그래밍: 데이터를 객체로 묶어 다루며, 객체는 데이터와 해당 데이터에 대한 메서드를 포함합니다. 따라서 데이터와 기능이 밀접하게 결합되어 있습니다. Java, C++, Python 등이 이에 해당합니다.

2. 모듈화

  • 절차 지향 프로그래밍: 모듈화는 함수 단위로 이루어지며, 각 함수가 독립적으로 동작합니다. 데이터는 여러 함수에 의해 접근되고 수정될 수 있습니다.
  • 객체 지향 프로그래밍: 모듈화는 객체 단위로 이루어지며, 객체는 자신의 상태(데이터)를 보호하고, 외부에서 직접 접근할 수 없도록 캡슐화합니다. 이를 통해 데이터의 무결성을 유지할 수 있습니다.

3. 상속과 다형성

  • 절차 지향 프로그래밍: 상속 개념이 없거나 제한적이며, 함수의 재사용은 주로 복사 및 수정에 의존합니다.
  • 객체 지향 프로그래밍: 상속을 통해 기존 클래스를 확장할 수 있으며, 다형성을 통해 같은 메서드가 서로 다른 형태로 동작할 수 있습니다. 이를 통해 코드의 재사용성과 유연성을 높입니다.

4. 유지보수

  • 절차 지향 프로그래밍: 프로그램이 커지면 코드의 복잡도가 증가하고, 유지보수가 어려워질 수 있습니다. 함수 간의 의존성이 높아지기 때문입니다.
  • 객체 지향 프로그래밍: 객체 단위로 나누어져 있어 유지보수가 용이하며, 새로운 기능 추가 시 기존 코드에 미치는 영향을 최소화할 수 있습니다.
Game game = new Game();
game.play();

 

class Game {
    int randNum;
    int guessNum;
    boolean result;
    int win = 0;
    int lose = 0;

    Scanner sc = new Scanner(System.in);    // 멤버 변수 -> heap 영역에 올라가 있음

    // 주사위의 랜덤 숫자 결정
    void init() {   // initialize (초기화)
        result = false;
        randNum = (int)(Math.random() * 6) + 1;
    }

    // 유저 인풋 받기
    void userInput() {
        // Scanner sc = new Scanner(System.in);     // --> Stack에 올라가 있음
        System.out.print("예측 숫자 입력 >>> ");
        guessNum = sc.nextInt();
    }

    // 판정
    void finding() {
        if (randNum == guessNum) {
            result = true;
            win++;
        } else {
            lose++;
        }
    }
    // 판정 결과
    void result() {
        System.out.println("주사위 수 = " + randNum);
        if (result) {
            System.out.println("정답입니다!");
            System.out.println("승률: " + win + "승" + lose + "패");
        } else {
            System.out.println("틀렸습니다.");
            System.out.println("승률: " + win + "승" + lose + "패");
        }
    }

    void play() {
        while (true) {
            init();
            userInput();
            finding();
            result();

            System.out.print("play again? (y/n) >>> ");
            String msg = sc.next();
            if (msg.equals("n") || msg.equals("N")) {
                System.out.println("안녕히 가십시오.");
                break;
            }
        }
    }
}

실행결과

 

+ Recent posts