[Java] #14 생성자

febCho·2023년 11월 7일
0

Java

목록 보기
35/53

앞서 객체의 개념에 대해 공부하며 생성자를 언급한 적이 있다.
참고) 객체의 개념

이번 게시물에서는 '생성자'가 무엇이고, 어떤 역할을 하는지 조금 더 자세히 알아보자.

생성자

생성자의 개념을 이해하기 위해 먼저 클래스의 전체 구조를 생략 없이 전부 명시해보았다.
클래스의 구조

1. 생성자의 개념

package kr.s15.object.constructor;

class Car{
	//멤버 변수
	String color;
	String gearType;
	int door;
	
	//기본 생성자
	public Car() {}
}
public class CarMain01 {
	public static void main(String[] args) {
		//객체 선언 및 생성
		Car c1 = new Car();
		System.out.println(c1.color + ", " + c1.gearType + ", " + c1.door);
		
		//멤버 변수의 데이터 변경
		c1.color = "white";
		c1.gearType = "auto";
		c1.door = 4;
		
		System.out.println(c1.color + ", " + c1.gearType + ", " + c1.door);
		
	}
}
  1. 기존 예제와 달리, 기본 생성자라는 항목이 눈에 띈다. 앞선 예제에서 객체를 생성할 때는 생략하였기 때문이다.
    여기서 알 수 있듯 public Car() {}와 같은 기본 생성자는 생략 가능하며, 이는 컴파일 시에 컴파일러가 생략된 기본 생성자를 만들어 주기 때문이다.

  2. 그리고 생성자는 객체 생성 시 단 한 번 실행되고 객체 생성 이후에는 호출이 불가능하다.

  3. 호출 시에는 1) 멤버변수를 초기화하는 역할을 수행한다. 따라서 위 예제에서 명시한 String color;와 같이 멤버변수들에 값을 대입하지 않고
    System.out.println(c1.color + ", " + c1.gearType + ", " + c1.door); 출력하였을 경우,

    출력)
    null, null, 0

    기본값이 출력되는 것을 확인할 수 있다.
    따라서 우리는 초기화를 담당하는 생성자를 '오버로딩'하여 기본값이 다양한 객체들을 생성할 수 있다.

2. 생성자 오버로딩

package kr.s15.object.constructor;

class Car2{
	String color;
	String gearType;
	int door;
	
	//생성자 오버로딩
	public Car2() {}
	
	public Car2(String c, String g, int d) {
		color = c;
		gearType = g;
		door = d;
	}
}

public class CarMain02 {
	public static void main(String[] args) {
		Car2 c1 = new Car2();
		c1.color = "white";
		c1.gearType = "auto";
		c1.door = 2;
		
		System.out.println(c1.color + "," + c1.gearType + "," + c1.door);
		System.out.println("=========================");
		
		//인자가 있는 생성자로 출력하기
		Car2 c2 = new Car2("blue", "manual", 5);
		System.out.println(c2.color + "," + c2.gearType + "," + c2.door);
	}
}
  1. 메서드처럼 생성자 오버로딩이 가능해 한 클래스는 기본 생성자 외에 같은 이름을 가진 다른 생성자를 가질 수 있다.
    참고) 메서드 오버로딩

  2. 단, 기본 생성자 없이 생성자 오버로딩을 한 다른 생성자만 존재할 경우, 컴파일러가 기본 생성자를 생성하지 않기 때문에 기본 생성자로 객체를 생성하려고 할 경우 오류가 발생한다.
    기본 생성자가 없으면

  1. 생성자는 멤버 변수를 초기화하는 역할 외에 2) 생성자 내부에서 특정 작업을 수행할 수 있고 3) 데이터를 인자에 전달하여 전달받은 데이터를 활용할 수도 있다.
	ex)
	public Car2(String c, String g, int d) {
			color = c;
			gearType = g;
			door = d;
		}
  1. 기본 생성자를 사용하여 객체를 생성할 경우 각 멤버변수를 기본값으로 초기화하기 때문에 이후에 값을 세팅해 주는 과정이 필요하지만(2 steps), 생성자 오버로딩을 통해 인자가 있는 생성자를 만들어 객체를 생성할 경우, 인자로 값을 넘겨주기만 하면(1 step) 따로 값을 세팅해줄 필요가 없다.

위에서 배운 생성자 오버로딩 개념을 적용하여 성적 프로그램을 만들어보았다.
> 생성자를 활용해 성적 프로그램 만들기


또한, 9월 8일 생성자 오버로딩과 은닉화/캡슐화, this 개념을 적용하여 실습을 진행하였다.
참고) 은닉화/캡슐화
참고) this/tihs()

실습 문제

  • Animal.java
	 * [실습]
	 * 1. 멤버 변수: 이름(name), 나이(age), 비행 여부(fly)
	 * 2. 생성자 지정: 인자 없는 생성자, 인자가 있는 생성(name, age, fly)
	 * 3. set/get 지정 : 멤버 변수를 private으로 지정하고 public한 set/get 메서드 정의
  • AnimalMain.java
	 * [실습]
	 * 1. 객체 생성 : 인자가 있는 생성자로 객체 생성
	 * 2. 생성된 객체의 멤버 변수에 저장된 정보 출력
	 *    이름 : 기러기
	 *    나이 : 3살
	 *    비행 여부 : 가능
	 * 3. 객체 생성 : 인자가 없는 생성자로 객체 생성
	 * 4. 이름, 나이, 비행 여부를 저장
	 * 5. 생성된 객체의 멤버 변수에 저장된 정보 출력
	 *    이름 : 기린
	 *    나이 : 10살
	 *    비행 여부 : 불가능

실습 풀이

  • Animal.java
package kr.s17.object.trainning;

public class Animal {
	
	private String name;
	private int age;
	private boolean fly;
	
	public Animal() {}
	
	public Animal(String name, int age, boolean fly) {
		this.name = name;
		this.age = age;
		this.fly = fly;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public void setAge(int age) {
		this.age = age;
	}
	
	public void setFly(boolean fly) {
		this.fly = fly;
	}
	
	public String getName() {
		return name;
	}
	
	public int getAge() {
		return age;
	}
	
	public boolean isFly() {
		return fly;
		}
	}
  1. 문제에 따라 멤버 변수를 private으로 지정(은닉화)한다.

  2. Animal 클래스의 인자가 없는 생성자 즉, 기본 생성자를 만든다.
    ex. public Animal(){}

  3. 생성자 오버로딩을 통해 인자가 있는 생성자를 만든다. 이때, 인자로 전달받은 name, age, fly를 객체의 은닉화된 멤버 변수에 대입해준다.
    ex. this.name = name;

  4. 아래 과정을 통해 캡슐화(set(), get() 메서드 정의)을 진행한다.
    ① 마우스 우클릭
    ② source
    ③ Generate Getters and Setters
    ④ select All > Generate 클릭
    getters and setters

  5. 이때 눈여겨볼 것은 boolean 타입의 은닉화된 변수에서 데이터를 뽑아내는 메서드는 getFly()가 아닌 isFly()라는 점이다.


  • AnimalMain.java
package kr.s17.object.trainning;

public class AnimalMain {

	public static void main(String[] args) {
		Animal first = new Animal("독수리", 5, true);
		
		System.out.println("이름 : " + first.getName());
		System.out.println("나이 : " + first.getAge() + "살");
		System.out.println("비행 여부 : " + printFly(first.isFly()));
		
		System.out.println("===============");
		
		Animal second = new Animal();
		
		second.setName("말티즈");
		second.setAge(2);
		second.setFly(false);
		
		System.out.println("이름 : " + second.getName());
		System.out.println("나이 : " + second.getAge() + "살");
		System.out.println("비행 여부 : " + printFly(second.isFly()));
	}
	
	public static String printFly(boolean fly) {
		return fly ? "가능" : "불가능";
	}
}
  1. 인자가 있는 생성자 public Animal(String name, int age, boolean fly) {의 경우, 인자로 각 타입에 맞는 데이터를 객체 생성 시에 바로 넘겨주면, 멤버 변수에 전달 받은 데이터를 대입 this.age = age; 해준다. 따라서 set() 메서드를 사용할 필요가 없다.

  2. 출력 시에는 은닉화되어 있는 멤버 변수에 get() 메서드로 접근해 값을 읽어온다.
    ex. System.out.println("이름 : " + first.getName());

  3. 이때 first.isFly()와 같은 boolean 타입은 true 혹은 false로 데이터가 출력되는데, 실습 문제에 따르면 '가능'과 '불가능'이 표기되어야 한다.
    따라서 boolean 타입의 데이터를 한 번 가공하기 위해 조건(삼항) 연산자를 사용한다.
    참고) 5. 조건(삼항) 연산자

  4. 메인 영역 바깥에서 boolean 타입의 데이터를 인자로 받고, String 타입의 데이터를 반환하는 메서드를 생성한다.
    ex. public static String printFly(boolean fly) {

  5. return 값을 명시할 때, 조건(삼항) 연산자를 넣어 전달 받은 boolean 타입의 데이터를 조건 체크 해주고, 참이면 "가능" 거짓이면 "불가능"을 반환하게 한다.
    ex. return fly ? "가능" : "불가능";

[boolean 타입의 데이터 출력 과정]
① isFly() 메서드를 통해 Animal 객체의 boolean 타입 데이터 fly를 반환한다.
② 그 값(fly)은 printFly() 메서드의 인자로 전달된다.
③ 그 값이 true면, "가능"을 반환하고
④ false라면, "불가능"을 반환한다.

  1. 따라서 비행 여부를 명시할 경우에는 isFly() 메서드를 PrintFly() 메서드로 감싼다.
    ex. System.out.println("비행 여부 : " + printFly(first.isFly()));

  2. 인자가 없는 생성자 public Animal() {}의 경우, 객체만 먼저 생성한다.

  3. 그리고 set() 메서드를 통해 각 타입에 맞는 메서드를 인자로 넘겨 멤버 변수에 저장해준다.
    ex. second.setName("말티즈");

  4. 출력 시에는 get() 메서드를 호출, boolean 타입의 메서드는 PrintFly()로 감싼 isFly() 메서드를 호출한다.

profile
Done is better than perfect.

0개의 댓글