6-2. 클래스와 객체

Hyun Jun·2022년 1월 22일
0

자바의 정석

목록 보기
21/52
post-thumbnail
post-custom-banner

u# 클래스와 객체

정의와 용도

클래스객체
정의객체를 정의해놓은 것실제로 존재하는 사물 또는 개념
용도객체 생성객체가 가진 기능과 속성에 따라 다름

프로그래밍에서의 객체: 클래스에 정의된 내용대로 메모리에 생성된 것

 

객체와 인스턴스

클래스(틀, 설계도)로부터 만들어진 객체를 인스턴스(instance)라고 함. 객체와 인스턴스는 같은 의미지만, 굳이 의미를 구분하자면,

  • 객체: 모든 인스턴스를 대표하는 보다 포괄적인 의미

  • 인스턴스: 어떤 클래스로부터 만들어졌는지를 강조하는 보다 구체적인 의미

 

클래스 → 인스턴스(객체)

ex) TV 설계도 → TV

사람이 TV를 보기 위해서는 TV(객체)가 필요한 것이지, TV 설계도(클래스)가 필요한 것은 아님.

TV 설계도(클래스)는 TV(객체)를 만드는 데에만 사용될 뿐.

 

객체의 구성요소

객체는 속성기능의 집합.
객체가 가지고 있는 속성과 기능을 멤버(member)라고 함.

클래스는 객체를 만들기 위한 설계도이므로, 클래스에는 객체가 가질 수 있는 모든 속성과 기능이 정의되어있음.

 

1. 속성 (property)

멤버 변수(member variable), 특성(attribute), 필드(field), 상태(state)

 

2. 기능 (function)

메서드(method), 함수(function), 행위(behavior)

 

ex) TV 클래스

속성너비, 높이, 전원 상태, 채널, 볼륨 등
기능전원 켜기/끄기, 채널 변경하기, 볼륨 높이기/낮추기 등

 

이를 클래스의 멤버 변수와 메서드로 만들어보면,

class Television {
    // 멤버 변수
    int width;
    int height;
    boolean isOn;
    int channel;

    // 메서드
    int getSize() { return width * height; };
    void togglePower() { isOn = !isOn; };
    void channelUp() { channel++; };
    void channelDown() { channel--; };
}

 

인스턴스의 생성과 사용

클래스명 변수명;
변수명 = new 클래스명();

ex) 클래스 Television의 인스턴스를 생성

Television exampleTV; // Television 클래스 타입의 새 참조변수 생성
exampleTV = new Television(); // Television의 인스턴스를 생성하고, 해당 객체의 주소값을 참조변수에 담음

인스턴스를 생성할 때, 인스턴스가 가진 멤버 변수들은 전부 각 타입에 맞는 기본값으로 설정됨. (int는 0, booleanfalse 등...)

 

인스턴스를 가리키고 있는 참조변수를 통해서 멤버 변수와 메서드를 조작할 수 있음.

class Test1 {
    public static void main(String[] args) {
        Television exampleTV;
        exampleTV = new Television();
        exampleTV.channel = 20; // 인스턴스의 멤버 변수 channel에 접근하여 값을 지정
        exampleTV.channelUp(); // 인스턴스의 메서드 channelUp을 호출 (채널 1 증가)
        System.out.printf("현재 채널은 %d번 입니다.", exampleTV.channel);
    }
}

 

하나의 인스턴스를 여러 개의 참조변수가 가리키는 것도 가능함.

class Test2 {
    public static void main(String[] args) {
        Television tv1 = new Television();
        Television tv2 = new Television();

        tv2 = tv1; // tv1이 갖고 있는 객체 주소를 tv2에 저장
        tv1.channel = 7;
        System.out.printf("tv2의 채널은 %d번 입니다.", tv2.channel); // 출력 값: tv2의 채널은 7번 입니다.
    }
}

원래 tv1tv2는 서로 다른 객체 주소를 저장하고 있었으나, tv2tv1의 객체 주소를 저장해줌으로써 이 두 참조변수가 하나의 인스턴스를 가리키게 되었음.

이렇게 되면 기존에 tv2가 가리키던 인스턴스는 더 이상 자신을 가리키는 참조변수가 없으므로 GC에 의해 자동적으로 메모리에서 제거됨.

 

객체 배열

객체로 이루어진 배열을 객체 배열이라고 함. 이 때 배열에 저장되는 것은 객체 자체는 아니고, 객체의 주소값임. 따라서 객체 배열은 참조 변수들을 묶은 배열이라고 볼 수 있음.

Television[] tv1, tv2, tv3;
Television[] tvArr = new Television[3];

배열의 원소인 tv1, tv2, tv3는 참조 변수의 기본값인 null로 초기화 되어있음. (각 원소가 아무것도 가리키고 있지 않음)

 

각 원소(참조 변수)마다 새 인스턴스를 생성하여 주소값을 할당해주어야 비로소 진짜 객체 배열을 생성한 것.

tvArr[0] = new Television();
tvArr[1] = new Television();
tvArr[2] = new Television();

 

초기화 블럭{}을 사용하여 조금 더 간편하게

Television[] tvArr = { new Television(), new Television(), new Television() };

객체의 개수가 많다면 for문 사용

Television[] tvArr = new Television[77];

for (int i = 0; i < tvArr.length; i++) {
    tvArr[i] = new Television();
}

 

클래스의 또 다른 정의

1. 데이터와 함수의 결합

프로그래밍 언어의 데이터 저장형태 발전 과정:

변수 → 배열 → 구조체 → 클래스

클래스: 데이터와 함수의 결합. 가장 고도화된 데이터 저장 형태

 

데이터와 함수는 클래스의 등장 이전까지는 별개로 취급되어 왔으나, 결국 데이터를 가지고 함수를 다루기 때문에 둘은 유관하며 함께 묶어줄 필요가 있음.

C언어에서는 문자열을 문자의 배열로 취급하지만, 객체지향 언어인 Java에서는 문자열을 String이라는 하나의 클래스로 다룸. 문자열과 문자열을 다루는 함수들을 함께 묶기 위함.

 

2. 사용자 정의 타입

언어에서 제공하는 기본형 타입 외에 프로그래머가 새롭게 만든 타입을 사용자 정의 타입이라고 함. Java에서는 class가 곧 사용자 정의 타입.

 

👨‍💻 예시를 통한 객체지향적 코드와 비객체지향적 코드 비교

비객체지향적 코드

시간을 나타내기 위해 시, 분, 초 3개의 변수를 선언

int hour;
int minute;
int second;

다루고자 하는 시간이 여러 개로 늘어난다면 배열로 처리할 수 있음. (3개라고 가정)

int[] hour = new int[3];
int[] minute = new int[3];
int[] second = new int[3];

배열로 다루면 종류별로 변수를 여러번 선언해야하는 수고는 덜지만, 시간을 이루는 3개의 요소가 서로 분리되어있어 프로그램 안에서 시간(시 + 분 + 초) 데이터를 다루기에 비효율적임.

 

객체지향적 코드

Time(시간)이라는 클래스를 정의하여 사용하면 훨씬 직관적이고 효율적인 데이터 활용 가능.

class Time {
    int hour;
    int minute;
    int second;
}

이제 시, 분, 초가 하나의 묶음으로 다뤄짐 (Time은 새로운 사용자 정의 타입처럼 쓰임)

Time t1 = new Time();
Time t2 = new Time();
Time t3 = new Time();

여러 개의 시간 객체를 배열로 묶을 수도 있음

Time[] t = new Time[3];
t[0] = new Time();
t[1] = new Time();
t[2] = new Time();

시간 데이터를 보다 정확하게 다루려면 시, 분, 초에 범위를 정해주어야 함.

(시의 범위: 0 ~ 23, 분과 초의 범위: 0 ~ 59)

객체지향언어는 제어자메서드를 통해 이러한 조건들을 코드에 쉽게 반영할 수 있다는 장점이 있음. (이 후의 챕터에서 다뤄질 개념)

 

아직 다루지 않은 부분이므로 참고만

public class Time {
    // private 제어자로 변수의 값을 직접 변경하지 못하도록 함
    private int hour;
    private int minute;
    private int second;

    // 메서드를 통해 각 변수의 값을 읽을 수 있도록 함
    public int getHour() { return hour; }
    public int getMinute() { return minute; }
    public int getSecond() { return second; }

    // 메서드를 통해 조건에 부합하는 경우에만 값을 변경할 수 있게 함
    public void setHour(int h) {
        if (h < 0 || h > 23) return;
        hour = h;
    }

    public void setMinute(int m) {
        if (m < 0 || m > 59) return;
        minute = m;
    }

    public void setSecond(int s) {
        if (s < 0 || s > 59) return;
        second = s;
    }
}
profile
Back-end Engineer 👨‍💻
post-custom-banner

0개의 댓글