개발공부

JAVA쪼렙탈출기: 클래스 (Class)

Yuniverse. 2023. 6. 3. 08:15
Python과 SQL만 써본 주니어 분석가. '개발공부를 해보고 싶다', '개발도 공부하긴 해야하는데...'는 말만 한지 어연 1년이 넘어가는 중, 이대로는 안되겠다 싶어 냅다 JAVA 수업 수강에 카드를 긁었다. 쪼렙 중의 쪼렙이 JAVA를 배워나가는 여정을 "JAVA 쪼렙 탈출기"라는 시리즈로 남길 예정이다.

 

JAVA는 객체 지향 프로그램(OOP : Object Oriented Programming)이다. 즉, Class를 사용해서 객체를 생성하고, 이렇게 만들어진 객체를 사용해서 하나의 프로그램을 만든다.

 

class

  • 객체를 만들기 위한 설계도
  • 객체에 대한 속성과 기능을 코드로서 구현한 것
  • class는 '멤버 필드'와 '멤버 메서드'로 구성된다.
    • 멤버 필드 : 변수(instance 변수) ➡️ 객체 고유의 데이터
    • 멤버 메서드 : 객체 기능과 동작을 구현

객체 (Object)

  • class를 사용해서 만들어지며, instance라고도 한다.
  • 하나의 class로 여러 개의 instance를 생성할 수 있다.

 

class Human { 
	
	// 멤버 필드
	String name;
	int age;
	
	// 멤버 메서드
	void info() {
		System.out.println("이름 : " + name);
		System.out.println("나이 : " + age + "세");
	}
	
}

public class ClassBasic {
	
	public static void main(String[] args) {
		
		Human manA; // Human 객체를 참조할 참조변수 생성 (class 변수를 만들었다고해서 객체까지 만들어지는 것은 아님)
		manA = new Human(); // Human 클래스의 객체 생성
		
		// 만약 위의 Human 클래스에서 멤버 메서드를 작성 안했다면 아래와 같이 이 지역에서 써서 출력해야 한다.
		manA.name = "manA";
		manA.age = 20;
		System.out.println("이름 : " + manA.name);
		System.out.println("나이 : " + manA.age + "세");
		System.out.println();
		
		
		// 하지만 위에서 멤버 메서드를 작성했다면 바로 출력할 수 있다. (일일이 쓸 필요x)
		manA.info();
		System.out.println();
		
		
		Human manB = new Human();
		manB.name = "manB";
		manB.age = 50;
		manB.info();
		System.out.println();
		
	}

}

이는 하나의 파일에 2개의 클래스를 생성한 경우이다. public 접근제한자는 파일명과 동일한 클래스에만 적용할 수 있기 때문에, 상단의 Human 클래스에는 public 접근제한자를 쓰지 않았다. (코드를 작성한 파일명 : ClassBasic) 보통은 파일 1개에 클래스 1개를 쓰는 게 일반적이다.

 

자동차의 정보를 저장하는 Car 클래스를 생성해보자.

public class Car {
	
	String company;	// 제조회사
	String model;	// 모델명
	String color;	// 색상
	int price;		// 가격
	
	// 멤버필드 설정
	void setCar(String _company, String _model, String _color, int _price) {
		company = _company;
		model = _model;
		color = _color;
		price = _price;
	}
	
	// 차량 정보 확인
	void info() {
		System.out.println("--- 차량 정보 ---");
		System.out.println("제조회사 : " + company);
		System.out.println("모델명 : " + model);
		System.out.println("색상 : " + color);
		System.out.println("가격 : " + price + "만원");
	}

}

이제 자동차를 관리하는 CarManager 클래스에서 Car 클래스를 호출해서 자동차 정보를 확인해보자.

public class CarManager {
	
	public static void main(String[] args) {
		
		Car carA = new Car(); // Car class를 불러온다.
		carA.setCar("KIA", "EV6", "Black", 5700);
		carA.info();
		
	}

}

[결과값]

--- 차량 정보 ---

제조회사 : KIA

모델명 : EV6

색상 : Black

가격 : 5700만원

 

 

메서드 오버로딩 (Method Overloading)

  • class 안에 같은 이름의 메서드를 여러 개 정의하는 것
  • 매개변수 개수, 타입만 다르면 하나의 이름으로 여러 개의 메서드를 정의할 수 있다.

메서드 오버로딩을 사용하지 않았을 때

class Plus {
	
	void addInt(int a, int b) {
		System.out.println(" - addInt(int a, int b) -");
		int sum = a + b;
		resultInt(a, b, sum);
	}
	
	void addDouble(double a, double b) {
		System.out.println(" - addDouble(double a, double b) -");
		double sum = a + b;
		resultDouble(a, b, sum);
	}
	
	void resultInt(int a, int b, int sum) {
		System.out.println(a + " + " + b + " = " + sum);
	}
	
	void resultDouble(double a, double b, double sum) {
		System.out.println(a + " + " + b + " = " + sum);
	}
	
	
}

메서드 오버로딩을 사용했을 때

class Plus {
	
	void addData(int a, int b) {
		System.out.println(" - addData(int a, int b) -");
		int sum = a + b;
		resultData(a, b, sum);
	}
	
	void addData(double a, double b) {
		System.out.println(" - addData(double a, double b) -");
		double sum = a + b;
		resultData(a, b, sum);
	}
	
	void resultData(int a, int b, int sum) {
		System.out.println(a + " + " + b + " = " + sum);
	}
	
	void resultData(double a, double b, double sum) {
		System.out.println(a + " + " + b + " = " + sum);
	}
	
}

같은 이름의 메서드(addData, resultData)에 매개변수 타입(int, double)을 달리 하여 메서드를 정의했음을 알 수 있다.

 

 

Getter & Setter

class의 변수에 private 접근제한자가 걸려있으면 해당 클래스를 호출할 때 단순지정을 할 수 없다. 이 경우 getter, setter 메서드가 필요하다.

 

getter 메서드

  • class 외부에서 생성된 객체의 멤버필드를 사용하는 용도의 메서드
  • 작성 규칙 : get + 필드명

 

setter 메서드

  • class 외부에서 생성된 객체의 멤버필드를 설정하거나 수정하는 용도의 메서드
  • 작성 규칙 : set + 필드명
  • setter 메서드를 활용하면 필터링이 가능하다.
class Member {
	
	private String id;
	private String name;
	private int age;
	
	public String getId() {
		return id;
	}
	
	public void setId(String _id) {
		id = _id;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String _name) {
		if(_name.length() <= 10) // setter 메서드를 통하면 그냥 변수만 생성해줬을 때와 달리 필터링이 가능.
			name = _name;
		else
			System.out.println("이름은 10글자까지만 가능합니다.");
	}
	
	public int getAge() {
		return age;
	}
	
	public void setAge(int _age) {
		if(_age >= 0 && _age <= 130)
			age = _age;
		else
			System.out.println("나이는 0 ~ 130 사이만 가능합니다.");
	}
	
	public void info() {
		System.out.println("-- 회원정보 --");
		System.out.println("ID	: " + id);
		System.out.println("이름	: " + name);
		System.out.println("나이	: " + age + "세");
	}
	
}


public class GetterSetterEx {
	
	public static void main(String[] args) {
		
		Member manA = new Member();
		// Member에서 private를 쓰면 아래처럼 단순 지정을 할 수 없다.
		// manA.id = "m001";
		// manA.name = "manA";
		// manA.age = 20;
		
		manA.setId("m001");
		manA.setName("manA");
		manA.setAge(21);
		
		manA.info();
		
		System.out.println();
		
		// 하나하나 따로 불러와야할 때 getter 메서드가 필요하다.
		// 변수들이 다 private로 차단되어 있으니까 getter 메서드를 통하지 않고는 불러올 수 없다.
		System.out.println("회원 ID : " + manA.getId());
		System.out.println("회원 이름 : " + manA.getName());
		System.out.println("회원 나이 : " + manA.getAge());
		
	}

}

 

 

생성자 ( constructor )

  • class명과 동일한 이름을 사용하고, 객체를 초기화하는 용도로 사용된다.
  • 생성자를 정의하지 않으면 아무것도 진행하지 않는 기본생성자가 자동으로 만들어져 실행된다.
  • 생성자도 매개변수를 사용할 수 있기 때문에 오버로딩이 가능하다.
  • 생성자를 하나라도 정의하면 기본생성자는 자동으로 만들어지지 않는다. ➡️ 필요하다면 별도로 정의해줘야 한다.

 

생성자를 정의하지 않았을 때

public class Member {
	
	private String id;
	private String name;
	private int age;
	
	public String getId() {
		return id;
	}
	
	public void setId(String _id) {
		id = _id;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String _name) {
		if(_name.length() <= 10) // setter 메서드를 통하면 그냥 변수만 생성해줬을 때와 달리 필터링이 가능.
			name = _name;
		else
			System.out.println("이름은 10글자까지만 가능합니다.");
	}
	
	public int getAge() {
		return age;
	}
	
	public void setAge(int _age) {
		if(_age >= 0 && _age <= 130)
			age = _age;
		else
			System.out.println("나이는 0 ~ 130 사이만 가능합니다.");
	}
	
	public void info() {
		System.out.println("-- 회원정보 --");
		System.out.println("ID	: " + id);
		System.out.println("이름	: " + name);
		System.out.println("나이	: " + age + "세");
	}

}
public class MemberManager {
	
	public static void main(String[] args) {
		
		Member manA = new Member();
		manA.info();
		
	}

}

[결과값]

-- 회원정보 --

ID       : null

이름    : null

나이    : 0세

 

생성자를 정의했을 때

public class Member {
	
	private String id;
	private String name;
	private int age;
	
	// 생성자 정의
	public Member() {
		id = "none"; 
		name = "none";
	}

	public String getId() {
		return id;
	}
	
	public void setId(String _id) {
		id = _id;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String _name) {
		if(_name.length() <= 10) 
			name = _name;
		else
			System.out.println("이름은 10글자까지만 가능합니다.");
	}
	
	public int getAge() {
		return age;
	}
	
	public void setAge(int _age) {
		if(_age >= 0 && _age <= 130)
			age = _age;
		else
			System.out.println("나이는 0 ~ 130 사이만 가능합니다.");
	}
	
	public void info() {
		System.out.println("-- 회원정보 --");
		System.out.println("ID	: " + id);
		System.out.println("이름	: " + name);
		System.out.println("나이	: " + age + "세");
	}

}
public class MemberManager {
	
	public static void main(String[] args) {
		
		Member manA = new Member();
		manA.info();
		
	}

}

[결과값]

-- 회원정보 --

ID       : none

이름    : none

나이    : 0세

 

또한, 생성자를 아래와 같이 정의하면 MemberManager 클래스에서 변수마다 일일이 set할 필요가 없어진다.

public class Member {
	
	private String id;
	private String name;
	private int age;

	// 생성자 정의
	public Member(String _id, String _name, int _age) {
		System.out.println("-  Member(String _id, String _name, int _age) -");
		id = _id;
		name = _name;
		age = _age;
	}
	
	public String getId() {
		return id;
	}
	
	public void setId(String _id) {
		id = _id;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String _name) {
		if(_name.length() <= 10) // setter 메서드를 통하면 그냥 변수만 생성해줬을 때와 달리 필터링이 가능.
			name = _name;
		else
			System.out.println("이름은 10글자까지만 가능합니다.");
	}
	
	public int getAge() {
		return age;
	}
	
	public void setAge(int _age) {
		if(_age >= 0 && _age <= 130)
			age = _age;
		else
			System.out.println("나이는 0 ~ 130 사이만 가능합니다.");
	}
		
	public void info() {
		System.out.println("-- 회원정보 --");
		System.out.println("ID	: " + id);
		System.out.println("이름	: " + name);
		System.out.println("나이	: " + age + "세");
	}

}
public class MemberManager {
	
	public static void main(String[] args) {
		
		Member manB = new Member("m002", "manB", 20); // 객체를 만들 때 (괄호) 안에 생성자에 보낼 데이터를 작성하면 된다.
		manB.info();
		
	}

}

[결과값]

- Member(String _id, String _name, int _age) -

-- 회원정보 --

ID       : m002

이름    : manB

나이    : 20세

 

 

this()

  • class 안에 instance 멤버를 가리키는 참조 변수
  • 생성자에서 this() 를 이용하면 다른 생성자를 호출할 수 있다.
  • 생성자의 첫줄라인에서만 진행 가능하다.
  • 기본생성자 뿐만 아니라 다른 생성자도 호출할 수 있다.
  • this를 사용하면 매개변수와 멤버필드명을 동일하게 할 수 있다.
public class Member {
	
	private String id;
	private String name;
	private int age;
	
	public Member() {
		System.out.println("- Member() -");
		id = "none"; 
		name = "none";
	}
	
	public Member(String id) {
		this(); 
		this.id = id;
	}
	
	
	public Member(String id, String name, int age) {
		System.out.println("-  Member(String _id, String _name, int _age) -");
		this.id = id;
		this.name = name;
		this.age = age;
	}
	
	public String getId() {
		return id;
	}
	
	public void setId(String id) {
		this.id = id;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		if(name.length() <= 10)
			this.name = name;
		else
			System.out.println("이름은 10글자까지만 가능합니다.");
	}
	
	public int getAge() {
		return age;
	}
	
	public void setAge(int age) {
		if(age >= 0 && age <= 130)
			this.age = age;
		else
			System.out.println("나이는 0 ~ 130 사이만 가능합니다.");
	}
	
	public void info() {
		System.out.println("-- 회원정보 --");
		System.out.println("ID	: " + id);
		System.out.println("이름	: " + name);
		System.out.println("나이	: " + age + "세");
	}

}

this()를 사용하면 호출한 생성자와 동일값을 가질 때는 굳이 코드를 작성할 필요가 없어져 코드가 더 간결해진다.