본문 바로가기
프로그래밍 언어/자바

5. 다시 공부하는 자바 - 객체 지향 프로그래밍 3 (이것이 자바다)

by amobu0 2024. 6. 14.

이것이 자바다 라는 책을 보고 정리한 글이다.

https://m.hanbit.co.kr/store/books/book_view.html?p_code=B4861113361

 

이것이 자바다(개정판)

2015년 초판이 출간된 이후부터 지금까지 기본 개념에 충실한 설명으로 독자들에게 큰 사랑을 받아온 『이것이 자바다』의 개정판. 기존 Java 8 버전에 최신 Java 17 LTS 버전까지 아우르는 내용으로

m.hanbit.co.kr

 

Part 2 객체 지향 프로그래밍


인스턴스 멤버

필드와 메소드는 선언 방법에 따라 인스턴스 멤버와 정적 멤버로 분류할 수 있다. 인스턴스 멤버로 선언되면 객체 생성 후 사용할 수 있고, 정적 멤버로 선언되면 객체 생성 없이도 사용할 수 있다.

구분 설명
인스턴스(instance) 멤버 객체에 소속된 멤버
(객체를 생성해야만 사용할 수 있는 멤버)
정적(static) 멤버 클래스에 고정된 멤버
(객체 없이도 사용할 수 있는 멤버)

 


인스턴스 멤버 선언 및 사용

인스터스 멤버란 객체에 소속된 멤버를 말한다. 따라서 객체가 있어야만 사용할 수 있는 멤버다.

public class Car {
    
    //인스턴스 필드 선언
    int gas;
    
    //인스턴스 메소드 선언
    void setSpeed(int speed) {
        
    }

gas필드와 setSpeed() 메소드는 인스턴스 멤버이기 때문에 외부 클래스에서 사용하기 위해서는 Car 객체를 먼저 생성하고 참조 변수로 접근해서 사용해야 한다. gas 필드는 객체마다 따로 존재하며, setSpeed() 메소드는 각 객체마다 존재하지 않고 메소드 영역에 저장되고 공유된다.

메소드는 코드의 덩어리이므로 객체마다 저장한다면 중복 저장으로 인해 메모리 효율이 떨어진다.
따라서 메소드 코드는 메소드 영역에 두되 공유해서 사용하고, 이때 객체 없이는 사용하지 못하도록 제한을 걸어둔 것이다.

this 키워드

객체 내부에서는 인스턴스 멤버에 접근하기 위해 this를 사용할 수 있다. 객체는 자신을 'this'라고 한다. 생성자와 메소드의 매개변수명이 인스턴스 멤버인 필드명과 동일한 경우, 인스턴스 필드임을 강조하고자 할 때 this를 주로 사용한다.

public class Car {

    //인스턴스 필드 선언
    String model;
    int price;
    
    //생성자 선언
    public Car(String model, int price) {
        this.model = model; //매개변수를 필드에 대입
        this.price = price; //매개변수를 필드에 대입
    }
}

정적 멤버

자바는 클래스 로더를 이용해서 클래스를 메소드 영역에 저장하고 사용한다. 정적static 멤버란 메소드 영역의 클래스에 고정적으로 위치하는 멤버를 말한다. 그렇기 때문에 정적 멤버를 객체를 생성할 필요 없이 클래스를 통해 바로 사용이 가능하다.


정적 멤버 선언 및 사용

필드와 메소드는 모두 정적 멤버가 될 수 있다. 정적 필드와 정적 메소드로 선언하려면 static 키워드를 추가해야 한다. 객체마다 가지고 있을 필요성이 없는 공용적인 필드는 정적 필드로 선언하는 것이 좋다. 클래스가 메모리로 로딩되면 정적 멤버를 바로 사용할 수 있는데, 클래스 이름고 함께 도트(.) 연산자로 접근하면 된다.


final 필드와 상수

인스턴스 필드와 적정 필드는 언제든 값을 변경할 수 있다. 그러나 경우에 따라서 값을 변경하는 것을 막고 읽기만 허용해야 할 때가 있다. 이때 final 필드와 상수를 선언해서 사용한다.


final 필드 선언

final은 '최종적'이란 뜻을 가지고 있다. final 필드는 초기값이 저장되면 프로그램 실행 도중에 수정할 구 없게 된다. final 필드에 초기값을 줄 수 있는 방법은 두 가지 이다.

1. 필드 선언 시에 초기값 대입
2. 생성자에서 초기값 대입


상수 선언

불변의 값을 저장하는 필드를 자바에서는 상수(Constant)라고 부른다. 수학에서는 원주울 파이, 지구의 무게 및 둘레 등이 해당된다. 상수는 객체마다 저장할 필요가 없고, 여러 개의 값을 가져도 안되기 때문에 static이면서 final인 특성을 가져야 한다. 상수의 이름은 모두 대문자로 작성하는 것이 관레이다.

static final double PI = 3.14159;
static final double EARTH_SURFACE_AREA = 5.1478628093432E8;

접근 제한자

객체의 필드를 외부에서 변경하거나 메소드를 호출할 수 없도록 막아야 할 필요가 있다. 중요한 필드와 메소드가 외부로 노출되지 않도록 해 객체의 무결성 (결점이 없는 성질)을 유지하기 위해서이다. 자바는 이러한 기능을 구현하기 위해 접근 제한자(Access Modifier)를 사용한다.

접근 제한자 제한 대상 제한 범위
public 클래스, 필드, 생성자, 메소드 없음
protected 필드, 생성자, 메소드 같은 패키지이거나, 자식 객체만 사용가능
(default) 클래스, 필드, 생성자, 메소드 같은 패키지
private 필드, 생성자, 메소드 객체 내부

싱글톤 패턴

애플리케이션 전체에서 단 한 개의 객체만 생성해서 사용하고 싶다면 싱글톤(singleton) 패턴을 적용할 수 있다. 싱글톤 패턴의 핵심은 생성자를 private 접근 제한해서 외부에서 new 연산자로 생성자를 호출할 수 없도록 막는 것이다.

private 클래스 () {}

 

생성자를 호출할 수 없으니 외부에서 마음대로 객체를 생성하는 것이 불가능해진다. 대신 싱클톤 패턴이 제공하는 정적 메소드를 통해서 간접적으로 객체를 얻을 수 있다. 외부에서 객체를 얻는 유일한 방법은 getInstance() 메소드를 호출하는 것이다. getInstance()메소드가 리턴하는 객체는 정적 필드가 참조하는 싱글톤 객체이다.

싱글톤 패선의 전체 코드
같은 Singleton 객체


상속

상속은 부모가 자식에게 물려주는 행위를 말한다. 객제 지향 프로그램에서도 부모 클래스의 필드와 메소드를 자식 클래스에게 물려줄 수 있다. 상속은 이미 잘 개발된 클래스를 재사용해서 새로운 클래스를 만들기 때문에 중복되는 코드를 줄여 개발 시간을 단축시킨다. 현실에서 상속은 부모가 자식을 선택해서 물려주지만, 프로그램에서는 자식이 부모를 선택한다. 자식 클래스를 선언할 때 어떤 부모로부터 상속 받을 것인지 결정하고 부모클래스를 extends 뒤에 기술한다.

public class 자식클래스 extends 부모클래스 {}

 자바는 다른 언어와 달리 다중 상속은 허용하지 않는다. 즉, 여러 개의 부모 클래스를 상속할 수 없다. 단 한나의 부모 클래스만 와야 한다.


타입 변환

타입 변환이란 타입을 변화하는 것을 말한다. 이전 글에서 다룬 적이 있는데, 클래스도 마찬가지로 타입 변환이 있는데, 클래스의 타입 변환은 상속 관계에 있는 클래스 사이에서 발생한다.

 

자동 타입 변환은 의미 그대로 자동적으로 타입 변환이 일어나는 것을 말한다. 자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급될 수 있다. 부모 타입으로 자동 타입이 변환된 이후에 부모 클래스에 선언된 필드와 메소드만 접근이 가능하다.

 

강제 타입 변환은 자식 타입은 부모 타입으로 자동 변환되지만, 반대로 부모타입은 자식 타입으로 변환되지 않는다. 대신 캐스팅 연산자로 강제 타입 변환을 할 수 있다.

자식타입 변수 = (자식 타입) 부모타입객체;

 

부모 타입 객체를 자식 타입으로 무조건 강제 변환할 수 있는 것은 아니다. 자식 객체가 부모 타입으로 자동 변환된 후 다시 자식 타입으로 변환할 때 강제 타입 변환을 사용할 수 있다. 

Parent parent = new Child;    //자동 타입 변환
Child child = (Child) parent; //강제 타입 변환

자식 객체가 부모 타입으로 자동 변환하면 부모 타입에 선언된 필드와 메소드만 사용 가능하기 때문에, 만약 자식 타입에 선언된 필드나 메소드를 사용해야 한다면 강제 타입 변환을 해서 다시 자식 타입으로 변환해야하는 번거로움이 따른다.


다형성

다형성이란 사용 방법은 동일하지만 실행 결과가 다양하게 나오는 성질을 말한다. 자동차의 부품을 교환하면 성능이 다르게 나오듯이 객체는 부품과 같아서, 프로그램을 구성하는 객체를 바꾸면 프로그램의 실행 성능이 다르게 나올 수 있다.