Languages/Java

[HUFS/객체지향프로그래밍] #5 클래스

성중 2022. 12. 30. 14:31

객체

물리적으로 존재하거나 추상적으로 생각할 수 있는 것 중에서 자신의 속성을 가지며 식별 가능한 것을 객체(Object)라고 하며, 이는 속성(필드)동작(메소드)로 구성된다

 

객체, 필드, 메소드
메소드 호출을 통해 객체들이 상호작용
객체 간의 관계

  • 집합 관계: 부품과 완성품의 관계
  • 사용 관계: 객체 간의 상호작용
  • 상속 관계: 상위(부모) 객체를 기반으로 하위(자식) 객체를 생성
  • 객체 지향 프로그래밍: 집합/사용 관계에 있는 객체들을 설계/조립하여 프로그램 개발

 

클래스(Class)는 객체의 설계도라고 할 수 있으며 인스턴스(Instance)는 클래스로부터 만들어진 객체이다

 

클래스 설계 > 설계된 클래스로 사용할 객체 생성 > 객체 이용

클래스 선언

보통 객체를 구상한 후 클래스 이름을 결정하는데 다음과 같은 명명 규칙을 따른다

  • 하나 이상의 문자로 이루어질 것
  • 첫 글자에는 숫자가 올 수 없음
  • $, _외의 특수 문자는 사용할 수 없음
  • 자바 키워드는 사용할 수 없음

 

클래스이름.java로 소스 파일 생성 후 클래스 선언

클래스로부터 인스턴스를 생성하려면 new 연산자로 메모리 힙 영역에 객체를 생성해야 한다

 

클래스 변수에 객체의 번지를 저장해 사용 가능

클래스의 두 용도

  • 라이브러리(API) 클래스: 객체 생성 및 메소드 제공 역할
  • 실행 클래스: main() 메소드 제공 역할

 

클래스의 구성(멤버)

필드 선언

객체의 고유한 데이터를 필드(field)라고 하며 객체의 부품 및 현재 상태 데이터 등을 저장한다

 

자동차 객체 및 클래스의 필드

필드는 클래스 내에서 생성자와 메소드 영역을 제외하면 어디서든 선언 가능하다

 

초기값은 생략 가능하며 변수와 유사하지만 변수는 아님
초기값을 지정하지 않은 필드에 자동으로 설정되는 기본 초기값
클래스 내외부에서 필드 값을 읽고 변경 가능

생성자 선언

클래스의 생성자 역시 생략 가능하며, 이 경우 기본 생성자(default constructor)가 추가된다

* 기본 생성자가 있어서 모든 클래스는 new 생성자로 객체 생성 가능

 

바이트 코드 파일에 기본 생성자 자동 추가

생성자(constructor)는 클래스로부터 new 연산자로 객체를 생성할 때 호출되어 객체의 초기화를 담당한다

 

생성자 선언
매개변수로 필드 초기화
매개변수명은 필드명과 유사하게 할 것을 권장하고 완전 동일할 경우 this 사용

외부에서 제공되는 다양한 데이터를 사용하기 위해 매개변수가 다른 생성자를 여러 개 선언하는 것을 생성자 오버로딩(overloading)이라고 하며, 단순히 변수 이름만 바꾸는 것은 해당하지 않는다

 

매개변수의 타입/개수/순서가 다르게 선언

생성자 오버로딩에 중복 코드가 발생하기 때문에 this()를 사용해 생성자 내에서 다른 생성자를 호출해줄 수 있다

 

생성자 첫 줄에서만 허용
중복 코드 제거

메소드 선언

메소드 선언 시 리턴 타입을 선언부에 명시 (없는 경우 void)

return문의 리턴 값은 리턴 타입이거나 리턴 타입으로 변환될 수 있어야 하며, 리턴 값이 없는 경우에도 return; 을 마지막에 넣어 메소드 실행 종료를 강제해야 한다

 

매개변수 타입도 지정해야 하며 타입과 개수가 맞지 않을 경우 컴파일 에러
매개변수의 개수를 모를 경우
클래스 내외부에서 메소드 호출

생성자 오버로딩과 동일하게 메소드 오버로딩(overloading)도 존재하며, 마찬가지로 매개 변수의 타입, 개수, 순서 중 최소 하나가 달라야 한다

 

메소드 오버로딩 (JVM은 매개 값 타입으로 메소드를 선택)

인스턴스/정적 멤버

객체를 생성한 후 사용할 수 있는 필드와 메소드를 인스턴스(instance) 멤버라고 하며, 객체 내에서 인스턴스 멤버에게 접근하기 위해서 this를 주로 사용한다

 

객체(인스턴스)를 생성한 후 접근
객체 내에서 매개변수명이 필드명과 동일한 경우 필드임을 지정하기 위해서도 this 사용

클래스에 고정된 멤버로서 객체를 생성하지 않고 사용할 수 있는 필드와 메소드를 정적(static) 멤버라고 하며, static을 사용해 선언, 클래스 이름으로 접근한다

 

정적 멤버 선언
객체(인스턴스) 생성 없이 접근
인스턴스/정적 멤버 선택 기준

클래스 활용

전체 프로그램에서 단 하나의 객체만 만들도록 보장하는 기법을 싱글톤(Singleton)이라 한다

 

싱글톤 작성 방법

  • 클래스 외부에서 new 연산자를 통해 생성자 호출이 불가하도록 private 접근자 사용
  • 자신의 타입인 정적 필드 선언 후 자신의 객체를 생성해 초기화
  • 외부에서 호출할 수 있는 getInstance() 선언
  • 정적 필드에서 참조하는 자신의 객체 반환

 

싱글톤 패턴 (하나의 객체로 인식)

final 필드는 지정된 초기 값이 최종 값이 되어 프로그램 실행 중 수정 불가능하게 된다

* 클래스 내에서 필드 선언 시 초기화하거나 생성자에서 매개변수로 초기화

 

final 필드 예시

package sec05.exam05;

public class Person {
	final String nation = "Korea";
	final String ssn;
	String name;
	
	public Person(String ssn, String name) {
		this.ssn = ssn;
		this.name = name;
	}
}

불변 상수(constant) 값은 정적 final 필드로 대문자로 선언해준다

 

정적 final 필드(상수) 예시

package sec05.exam06;

public class Earth {
	static final double EARTH_RADIUS = 6400;
	static final double EARTH_AREA = 4 * Math.PI * EARTH_RADIUS * EARTH_RADIUS;
}

클래스 작성 시에는 해당 클래스가 어떤 패키지에 속할 것인지 패키지 선언해야 한다

* 다른 패키지에 소속된 클래스 또는 인터페이스 사용시 import문 사용

 

패키지 선언
import문

다른 패키지에 동일한 이름의 클래스가 있는 경우 사용 예시

package sec06.exam02.mycompany;

import sec06.exam02.hankook.*;
import sec06.exam02.kumho.*;
import sec06.exam02.hyndai.Engine;

public class Car {
	//필드
	Engine engine = new Engine();
	SnowTire tire1 = new SnowTire();
	BigWidthTire tire2 = new BigWidthTire();
	sec06.exam02.hankook.Tire tire3 = new sec06.exam02.hankook.Tire();
	sec06.exam02.kumho.Tire tire4 = new sec06.exam02.kumho.Tire();
}

접근 제한

접근 제한자(access modifier)는 클래스와 인터페이스 및 이들이 가진 멤버의 접근을 제한한다

 

접근 제한자

  • public 접근 제한자: 외부 패키지의 클래스도 자유롭게 사용 가능
  • protected 접근 제한자: 같은 패키지 또는 자식 클래스에서만 사용 가능
  • default 접근 제한자: 같은 패키지에 소속된 클래스에서만 사용 가능 (default 생략)
  • private 접근 제한자: 외부에서 사용 불가

 

  1. 클래스의 접근 제한의 경우 외부 패키지 사용 가능 여부에 따라 default/public 결정
  2. 생성자의 접근 제한의 경우 생성자 호출 가능 여부에 따라 4가지 결정
  3. 필드와 메소드의 접근 제한의 경우에도 위의 기준으로 4가지 결정

외부에서 객체를 마음대로 접근할 경우 무결성이 깨질 수 있으므로 Getter/Setter 메소드를 사용한다

 

Getter 메소드로 필드 값을 가공해 외부에 공개
Setter 메소드로 매개 값 검증 및 필드 값 변경