본문 바로가기

프로그래밍 공부/Java

Java - 클래스(Class)와 객체(Object)

객체 지향 프로그래밍(OOP, Object-Oriented Programming)

객체 지향 프로그래밍에서는 모든 데이터를 객체(Object)로서 취급한다. PHP와 JavaScript, Python, Rudy 그리고 Java 등의 대부분의 프로그래밍 언어들은 객체 지향 프로그래밍 언어라고 할 수 있다.

객체는 쉽게 설명하면 인식할 수 있는 사물이다. 이런 객체의 상태와 행동을 구체화 하는 프로그래밍이 객체 지향 프로그래밍이다. 이때 객체를 만들어 내기 위한 설계도와 같은 개념이 바로 클래스(Class)이다.

Java에서 클래스는 객체를 정의하는 틀 또는 설계도와 같은 의미로 사용이 된다. 클래스의 객체의 상태를 나타내는 필드(Field)와 객체의 행동을 나타내는 메서드(Method)로 구성이 된다. 따라서 필드란 클래스에 포함된 변수(Variable)를 의미한다. 그리고 메서드란 어떠한 특정 작업을 수행하기 위한 명령문의 집합이라고 생각하면 된다.

Java에서 클래스를 사용하기 위해서는 우선 해당 클래스 타입의 객체를 선언해야 한다. 이렇게 클래스로부터 객체를 선언하는 과정을 인스턴트화 라고 한다. 또한 이렇게 선언된 해당 클래스 타입의 객체를 인스턴스(Instance)라고 한다. 인스턴스란 메모리에 할당된 객체를 의미한다.

Java에서는 하나의 클래스로부터 여러 개의 인스턴스를 생성할 수 있다. 이렇게 생성된 인스턴스를 독립된 메모리 공간에 저장된 자신만의 필드를 가질 수 있다. 하지만 해당 클래스의 메서드는 해당 클래스에서 생성된 모든 인스턴스가 공유하게 된다.

Java는 프로토타입(Prototype)을 기반으로 하는 객체 지향 언어인 JavaScript와는 다르고 PHP와 Python과 유사하다고 볼 수 있다. 같은 객체 지향 언어라도 JavaScript는 클래스 기반이 아닌 프로토타입을 기반으로 하기 때문이다.

Java에서 클래스는 멤버(Member)로 속성을 표현하는 필드와 기능을 표현하는 메서드를 가진다. 그중에서 메서드란 특정 작업을 수행하기 위한 명령문의 집합이라고 할 수 있다. 

클래스는 객체 지향 프로그래밍의 추상화(Abstraction)라는 개념을 직접 구현한 것이라고 할 수 있다. Java에서는 개방자의 편의를 위해 유용하게 사용할 수 있는 많은 수의 클래스를 미리 정의하여 제공하고 있다. 

 

간단하게 class 키워드를 사용하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 클래스(Class)의 형태
점근제어자 class 클래스명{
    접근제어자 필드1의타입 필드1의이름;
    접근제어자 필드2의타입 필드2의이름;
    ...
    접근제어자 메서드1의원형
    접근제어자 메서드2의원형
    ...
};
 
class Car{                                   // 클래스(Class)의 이름
    private String modelName;                // 필드(Field)1
    private int modelYear;                   // 필드(Field)2
 
    Car(String modelName, int modelYear){    // 생성자(Constructor)
        this.modelName = modelName;
        this.modelYear = modelYear;
    }
    
    public String setModel(){                // 메서드(Method)
        return this.modelYear + "년식" + this.modelName + " " + this.color;
    }
};
cs

위와 같이 선언된 클래스의 정의를 가지고 만들어진 class Car에 Car 객체의 인스턴스를 생성할 수 있다. 먼저 객체를 참조하기 위한 참조 변수를 선언해야한다. 그리고 new 키워드를 사용해 인스턴스를 생성하고, 해당 인스턴스의 주소를 미리 선언한 참조 변수에 저장해 사용한다. 또한 참조 변수의 선언과 인스턴스의 생성을 동시에 할 수도 있다.

1
2
3
4
5
6
7
8
9
// 인스턴스(Instance)의 형태
클래스명 객체참조변수명;
Car myCar;
 
객체참조변수명 = new 클래스명();
myCar = new Car();
 
클래스명 객체참조변수명 = new 클래스명();
Car myCar = new Car();
cs

메서드는 JavaScript의 function과 같은 기능을 한다. 메서드의 형태는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 메서드(Method)의 형태
 
접근제어자 반환타입 메서드명 (매개변수1, 매개변수2...){
    // 구현부(이곳에 처리할 내용을 입력한다.)
};
 
1. 접근제어자 : 해당 메서드에 접근할 수 있는 범위(privateprotectedpublic 등)
2. 반환타입(return type) : 메서드가 모든 작업을 마치고 반환하는 데이터의 타입
3. 메서드명 : 메서드를 호출하기 위한 이름
4. 매개변수(parameters) : 메서드 호출시 전달되는 인수의 값을 저장할 변수
5. 구현부 : 메서드에서 처리할 내용
 
class Car{
    private int currentSpeed;
    private int accelerationTime;
    ...
 
    public void accelerate(int speed, int second){
        System.out.println(second + "초간 속도를 시속" + speed + "(으)로 가속함!");
    }
    ...
}
cs

Java에서 위와 같은 방법으로 정의한 메서드는 멤버 참소 연산자 '.'를 이용해 호출할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 메서드(Method)의 호출
1. 객체참조변수명.메서드명();                    // 매개변수가 없는 메서드의 호출
2. 객체참조변수명.메서드명(인수1, 인수2...);    // 매개변수가 있는 메서드의 호출
 
Car myCar = new Car();        // 객체를 생성
myCar.accelerate(603);    // myCar 인스턴스의 accelerate() 메서드를 호출
 
class Car{
    private int currentSpeed;
    private int accelerationTime;
 
    public void accelerate(int speed, int second){
        System.out.println(second + "초간 속도를 시속 " + speed + "(으)로 가속함!");
    }
}
 
public class Main{
    public static void main(String[] args){
        Car myCar = new Car();        // 객체 
        myCar.accelerate(603);    // 메서드 호출
    }
}
cs

Java에서는 객체의 생성과 동시에 인스턴스 변수를 원하는 값으로 초기화활 수 있는 생성자(Constructor)라는 메서드를 제공한다. Java에서 생성자의 이름은 해당 클래스의 이름과 같아야 한다. 따라서 Car 클래스의 생성자의 이름은 Car가 된다.

생성자의 특징은 3가지가 있다.
1. 생성자는 반환값이 없지만, 반환 타입을 void형으로 선언하지 않는다.
2. 생성자는 초기화를 위한 데이터를 인수로 전달받을 수 있다.
3. 객체를 초기화하는 방법이 여러개 존재할 경우 하나의 클래스가 여러 개의 생성자를 가질 수 있다. 따라서 생성자도 하나의 메서드이고, 메서드 오버로딩(Overloading)이 가능하다.

1
2
3
4
5
6
7
8
9
10
11
// 생성자(Constructor)의 형태
1. 클래스명(){...}                    // 매개변수가 없는 생성자
2. 클래스명(인수1, 인수2...){...}    // 매개변수가 있는 생성자
 
Car(String modelName, int modelYear, String color, int maxSpeed){
    this.modelName = modelName;
    this.modelYear = modelYear;
    this.color = color;
    this.maxSpeed = maxSpeed;
    this.currentSpeed = 0;
}
cs

Java에서 new 키워드를 사용하려 객체를 생성할 때 생성자가 호출이 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 생성자(Constructor)의 호출
class Car{
    private String modelName;
    private int modelYear;
    private String color;
    private int maxSpeed;
    private int currentSpeed;
 
    Car(String modelName, int modelYear, String color, int maxSpeed){
        this.modelName = modelName;
        this.modelYear = modelYear;
        this.color = color;
        this.maxSpeed = maxSpeed;
        this.currentSpeed = 0;
    }
    
    public String getModel(){
        return this.modelYear + "년식 " + this.modelName + " " + this.color;
    }
}
 
public class Main{
    public static void main(String[] args){
        Car myCar = new Car("아반떼"2016"흰색"200);    // 생성자 
        System.out.println(myCar.getModel());                // 생성자에 의해 초기화되었는지 확인
    }
}
cs

클래스의 필드는 클래스에 포함된 변수를 의미하는데, 크세 3가지로 분류가 된다.
1. 클래스 변수(Static Variable)
2. 인스턴스 변수(Instance Variable)
3. 지역 변수(Local Variable)

클래스 변수와 인스턴스 변수는 초기화를 하지 않아도 변수의 타입에 맞게 초기화가 된다. 하지만 지역 변수는 사용하지 전에 초기화를 하지 않으면 자바 컴파일러 오류가 발생한다.

1
2
3
4
5
6
7
8
9
// 필드(Field)의 구분
class Car{
    static int classVariable;    // 클래스 변수
    String instanceVariable;     // 인스턴스 변수
 
    void method(){
        int localVariable        // 지역 변수
    }
}
cs

여러 종류의 변수를 생성하고 참조하려면 아래의 코드를 참고한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Field{
    static int classVar = 10;    // 클래스 변수 선언
    inr instanceVar = 20;        // 인스턴스 변수 선언
}
 
public class Main{
    public static void main(String[] args){
        int var = 30;                        // 지역 변수 선언
        System.out.println(var + "\n");        // 지역 변수 참조
 
        Field myField1 = new Field();    // 인스턴스 선언
        Field myField2 = new Field();    // 인스턴스 참조
 
        System.out.println(Field.classVar);        // 클래스 변수 참조
        System.out.println(myField1.classVar);
        System.out.println(myField2.classVar + "\n");
 
        myField.classVar = 100;        // 클래스 변수의 값을 변경
 
        System.out.println(Field.classVar);        // 클래스 변수 참조
        System.out.println(myField1.classVar);
        System.out.println(myField2.classVar + "\n");
 
        System.out.println(myField1.instanceVar);    // 인스턴스 변수 참조
        System.out.println(myField1.instanceVar + "\n");
 
        myField.instanceVar = 200;    // 인스턴스 변수의 값을 변경
 
        System.out.println(myField1.instanceVar);    // 인스턴스 변수 
        System.out.println(myField1.instanceVar);
    }
}
cs