프로그래밍 언어 공부/Java 기초

[Java 스터디 두 번째] 클래스와 객체

always-dev 2022. 7. 17.
반응형

자바 스터디를 진행하고 있습니다.
개인적으로 공부한 내용을 바탕으로 정리하고 있으며
이상한 부분은 댓글에 남겨주시면 감사하겠습니다.

 

 

 

 

 

먼저 앞에서 [자바] 배열에서 객체지향 개념이 나오기 전 데이터와 기능이 따로따로 존재했다는 것을 배웠었다.

객체 지향 개념이 나오면서 데이터와 그와 관련된 기능을 클래스로 묶어서 사용할 수 있게 되었다고 했었다.

아래에서 클래스와 객체에 대해서 더 자세히 알아보자.

 

1. 클래스와 객체 (객체지향이론 관점, 프로그래밍 관점) 🚀

 

클래스는 데이터와 그와 관련된 기능(메소드)을 가지고 있다.

그리고 클래스는 객체를 생성하는데 사용이 된다.

 

생성된 객체는 기능과 데이터(속성)을 가지고 있다.

주의해야 할 것은 객체는 가지고 있는 기능과 속성에 따라 다르는 것이다.

 

클래스는 결국 객체를 생성해주는 역할을 가지고 있다.



객체지향이론 관점 : 클래스는 객체를 생성하기 위한 틀이고, 속성과 기능으로 정의되어 있다.



클래스는 객체지향이론 관점이 아닌 프로그래밍 관점에서도 볼 수 있는데

프로그래밍 관점 : 프로그래밍에서의 객체는 클래스에 정의된 내용대로 메모리에 생성한다는 뜻을 가지고 있다.

 

밑에서 더 프로그래밍적인 관점에서 더 자세히 알아보자.




1-1. 클래스의 또 다른 정의 (프로그래밍 관점)

클래스란 ?

서로 관련된 변수들을 정의하고 이들에 대한 작업을 수행하는 함수들을 함께 정의 한 것

 

1-1-1. 클래스 : 데이터와 함수의 결합

프로그래밍 언어에서 데이터를 처리하기 위한 데이터 저장형태 (+ 발전 과정)

데이터 저장 형태는 4가지가 있다.

  1. 변수 : 하나의 데이터를 저장할 수 있는 공간
  2. 배열 : 같은 종류를 여러 데이터를 하나의 집합으로 저장하는 공간
  3. 구조체 : 서로 관련된 여러 데이터를 종류에 관계없이 하나의 집합으로 저장하는 공간
  4. 클래스 : 데이터와 함수의 결합 (구조체 + 함수)



객체지향 개념이 있기 전에는 데이터와 함수를 따로 다루어져 왔지만,

함수는 주로 데이터와 항상 관계가 있기 때문에 관계가 깊었다.



그래서 객체지향개념이 나오면서 변수(데이터)와 함수를 하나의 클래스에 정의하여 함께 다룰 수 있게 됐다.



1-1-2. String 클래스가 존재하는 이유

이 얘기도 [자바]_배열에서 언급되었듯이

Java에서는 문자열을

char[]이 아닌 String클래스를 사용하는데

왜 클래스로 묶었을까에 대한 이유는

 

문자열을 다루는 함수를 클래스로 묶기 위해서이다.
public final class String implements java.io.Serializable, Comparable {
    private char[] value;

    public String replace(char oldChar, char newChar) {
        ...
        char[] val = value;
        ...
    }
}

위 코드는 String 클래스의 소스 일부이다.

클래스 내부에는

  • value라는 문자형 배열
  • 문자열을 다루는 데 필요한 함수들

을 함께 정의해 놓았다.

이렇게 하면 변수와 함수가 서로 유기적으로 연결되어 작업이 간단하고 명료해진다.




1-1-3. 사용자 정의 타입 (User-Defined Type)

재미있는 부분이 또 있다.

우리는 데이터 자료형 공부했을 때

  • 기본형(primitive type)이 8개인데
  • 참조형(reference type)은 몇개인지 알려주지 않았다.

그 이유는 바로 클래스에 사용자 정의 타입(user-defined type)이 있기 때문이다.

 

사용자 정의 타입을 정의할 때 다음과 같이 객체지향언어를 이용해 조건들을 코드에 쉽게 반영하자.

  • 제어자
    • 변수의 값을 직접 변경하지 못하도록 하고 대신 메서드를 통해서 값을 변경하도록 작성
  • 메서드
    • 메서드를 통해서 값을 변경하도록 작성
  • 조건문
    • 값을 변경할 때 지정된 유효성을 조건문으로 점검한 다음에 유효한 값일 경우에만 변경한다.

 

클래스에 대해서 알아보았으니 이제 객체에 대해서 알아보자



1-2. 객체와 인스턴스

자바를 사용하다보면

  • 객체,
  • 인스턴스,
  • 인스턴스화

같은 용어가 계속 나오는데 이 세 가지 용어의 차이를 말하기가 생각보다 쉽지 않을 수도 있다.

 

1-2-1.인스턴스화

먼저 인스턴스화에 대해 알아보자면

클래스로 부터 객체를 만드는 과정을 클래스의 인스턴스화(instantiate)라고 한다.

클래스로부터 만들어진 객체를 그 클래스의 인스턴스(instance)라고 한다.

 

🤷‍♂️ 아니 그러면 객체나 인스턴스나 똑같은 말 아닌가 ??

 

정확하게 구분하자면

객체는 모든 인스턴스를 대표하는 포괄적인 의미를 갖고 있다.

인스턴스는 어떤 클래스로부터 만들었는지를 강조하는, 보다 구체적인 의미를 지닌다.



다음은 인스턴스를 어떻게 생성해서 사용하는지 예제와 그림을 통해 알아보자.




1-3. 객체의 구성요소 (속성과 기능)

객체는 다수의 속성과 다수의 기능을 갖는다.

즉, 객체는 속성과 기능의 집합이다.

객체가 가지고 있는 속성과 기능을 그 객체의 멤버(구성원, member) 라고 한다.

 

속성과 기능에는 같은 뜻의 여러가지 용어가 있는데

주로

  • 속성(property) : 멤버변수(member variable)
  • 기능(function) : 메서드(method)

라고 사용한다.




1-4. 인스턴스의 생성과 사용

class Dog {
    // Dog의 속성(멤버변수)
    String name;
    boolean dangerous;
    int age;

    // Dog의 기능(메소드)
    void bark() {
        System.out.println(name); //강아지는 짖을 때 자신의 이름을 말한다.
    }
}

class DogTest {
    public static void main(String[] args) {
        Dog g;
        g = new Dog();
        g.name = "바둑이";
        g.age = 3;
        g.bark();
    }
}

인스턴스 생성과 인스턴스의 속성과 메소드가 어떤 식으로 변화되는지 알아보자.

 

위에 Dog클래스로부터 인스턴스를 생성하고 인스턴스의 속성과 메소드 사용 방법이다.

  1. Dog g;
    • Dog 클래스 타입의 참조변수 g를 선언한다.
    • 이 때 메모리에 참조변수 g를 위한 공간이 만들어진다.
      • 참소변수 g는 앞으로 생성될 인스턴스의 주소가 들어간다.
    • 아직 참조변수를 선언한 것 뿐이라 인스턴스는 존재하지 않다.
    • 때문에 아직 아무것도 할 수 없다.
  2. g = new Dog();
    • 연산자 new에 의해 Dog클래스의 인스턴스가 메모리의 빈 공간에 생성된다.
    • 멤버변수는 각 자료형의 기본값으로 자동 초기화된다.
    • 대입연산자 (=)에 의해서 생성된 객체의 주소값이 참조변수 g에 저장된다.
    • 인스턴스에 접근하기 위해서는 참조변수가 필요하다.
  3. g.name = "바둑이";
    • 참조변수.멤버변수
    • 참조변수 g에 저장된 주소에 있는 인스턴스의 멤버변수 name에 바둑이를 저장한다.



1-5. 객체 배열

객체 배열이라고 들어본 적이 있는가?

사용한다고 해도 List<Dog> 이런 식으로 사용해왔지 실제로 Dog[]로 사용해본 기억이 없다.

 

당연히 객체도 배열로 다룰 수 있다.

물론 객체 배열 안에 객체가 저장되는 것이 아닌 객체의 주소가 저장된다.

 

 

 

때문에 객체 배열은 참조변수들을 하나로 묶은 참조 변수 배열이다



간단하게 예제를 통해서 배우자 !

class DogTest {
    public static void main(String[] args) {

        Dog[] dogArr = new Dog[3]; // 길이가 3인 Dog 객체 배별

        // Dog 객체를 생성해서 Dog 객체 배열의 각 요소에 저장한다.
        for (int i = 0; i < dogArr.length; i++) {
            dogArr[i] = new Dog();
            dogArr[i].name = "바둑이" + i;
        }

        for (int i = 0; i < dogArr.length; i++) {
            System.out.println(dogArr[i].name);
        }
    }
}

class Dog {
    String name;
    boolean dangerous;
    int age;

    void bark() {
        System.out.println(name);
    }
}

모든 배열과 같이 객체 배열도 같은 타입의 객체만 저장할 수 있다.

 

또 주의할 점이 있는데 아래 코드를 봐보자

Dog[] dogArr = new Dog[3];

이 코드는 객체를 다루기 위한 참조변수들이 만들어진 것일 뿐이지 아직 객체가 생성된 상태가 아니다.




반응형

댓글