티스토리 뷰

🎈 이번 포스팅에서는 객체지향 프로그래밍의 가장 기본이 되는 클래스의 선언 방법과 생성자에 대해 알아봅니다.

 

#1> OOP(Obejct-Oriented Programming)의 시발점: 클래스

객체지향 프로그래밍 언어인 자바를 통해 프로그램을 만들기 위해 가장먼저 무엇을 하나요? 바로 적당한 이름의 클래스를 생성하는 것 부터 시작합니다. 자바 프로그래밍을 해보셨다면 아래와 같은 코드를 수도없이 많이 작성해보셨을 겁니다.

class MainClass {
  public static void main(String[] args) {
    // TODO: Programming
  }
}

위 클래스 선언을 코틀린 언어로 작성하면 바로 아래와 같이 됩니다.

class MainClass {
  companion object {
    fun main(args: Array<String>) {
      // TODO: Programming
    }
  }
}
🔊 코틀린 언어는 자바의 static 키워드를 지원하지 않습니다. 그 대신 패키지 수준의 최상위 함수와 객체 선언을 통해 static 메서드 역할을 대신합니다. 위 예제에서 companion object(동반객체)를 통해 클래스 안의 private맴버에 접근 할 수 있는 static 메서드를 선언합니다. 최상위니 동반이니 무슨말인지 잘 이해가 안되시면 일단은 이런게 있구나 하고 넘어가도 좋습니다. 추후 심화 포스팅에서 모두 다룰 예정입니다.

자바와 큰 차이가 없다고 생각하실 지 모르겠습니다. 하지만 코틀린과 자바의 클래스 선언 방식에 위 예제에서는 보이지 않는 작지만 큰 차이들이 있습니다. 그리고 그 차이들이 엄청난 편리성을 가져다줍니다.

 

본 포스팅에서는 그 차이와 그로 인해 발생하는 커다란 이점에 대해 이야기 합니다. 같이 살펴보시죠!

 

#2> 코틀린의 클래스

코틀린 예제에 단골로 등장하는 사람 이름과 나이를 저장하는 Person이라는 이름의 자바빈(JavaBean) 클래스를 만들어 보면서 코틀린 클래스에 대해 알아보겠습니다.

💡 자바빈(JavaBean)이란 자바빈 규격서에 따라 작성된 자바 클래스를 칭합니다. 기본 생성자를 가져야하고, 클래스의 프로퍼티는 게터와 세터를 구현해야 합니다.

클래스의 선언

우선 Person이라는 클래스를 정의해봅시다. 위 섹션에서 살펴본 것 처럼 클래스 선언을 할 때는 class 라는 키워드 뒤에 원하는 클래스 이름을 적어주면 됩니다.

class Person {}

참고로 코틀린의 클래스는 자바와 마찬가지로 기본 가시성이 public 입니다. 따라서 아래와 같이 선언해도 컴파일러는 위와 동일한 클래스 선언이라고 판단합니다.

public class Person {}

클래스 선언을 하긴 했지만 우리가 원하는 것은 이름과 나이 데이터를 담을 수 있는 프로퍼티(클래스 맴버 변수)를 가진 Person 클래스입니다.

 

클래스의 프로퍼티 선언

아래와 같이 이름과 나이를 담을 프로퍼티를 선언 할 수 있습니다. 코틀린의 프로퍼티는 기본적으로 선언과 동시에 초기화를 해줘야 합니다. 그렇지 않은 경우 컴파일 시 애러가 발생합니다.

class Person {
  var name: String = ""
  var age: Int = 0
}

보통 이런 model 역할을 하는 클래스는 프로퍼티를 초기화 하는 생성자가 필요합니다. 코틀린 클래스의 생성자는 java와는 조금 다른 문법을 가지고 있습니다.

 

#3> 코틀린의 클래스 생성자 (Kotlin Class Constructor)

클래스의 생성자

생성자는 constructor 라는 키워드를 통해 선언할 수 있습니다. 이 키워드를 사용해 name과 age 프로퍼티를 초기화 하는 생성자를 구현할 수 있습니다.

class Person {
  constructor (name: String, age: Int) {
    this.name = name
    this.age = age
  }
  var name: String = ""
  var age: Int = 0
}

뭔가 지저분해보이죠? 기본 생성자는 클래스 이름 옆에 선언할 수 있으며 constructor 키워드를 생략해도 됩니다. 따라서 위 클래스 선언과 아래 두가지 타입의 클래스 선언은 완전히 동일합니다.

// 클래스 이름 옆에 선언된 기본 생성자
class Person constructor (name: String, age: Int) {
  var name: String = name
  var age: Int = age
}

// 생성자 키워드를 생략한 형태
class Person (name: String, age: Int) {
  var name: String = name
  var age: Int = age
}

클래스 생성자 오버로드(overload)

기본 생성자는 유지하되, 클래스 생성 시 name 프로퍼티만 초기화하고 age는 기본 값인 0으로 설정하는 생성자를 선언하고 싶다면 어떻게 해야할까요? 바로 아래와 같이 constructor 키워드를 통해 생성자를 오버로드 해주면 됩니다.

class Person (name: String, age: Int) {
	constructor(name: String) {
		this.name = name
		this.age = 0
	}
  var name: String = name
  var age: Int = age
}

val p1 = Person("생각하는", 20) // name="생각하는", age=20
val p2 = Person("개발자")       // name="개발자", age=0

자바 스타일의 개발에 익숙하신 분들이라면 이런 오버로드를 많게는 5개 이상까지도 작성해본 경험이 있으실 겁니다. 하지만 코틀린은 기본값이라는 개념을 통해 파라미터 갯수에 따라 생성자를 반복적으로 선언하는 일이 없도록 해줍니다.

 

파라미터의 기본값(default value) 설정

우선 아래 코드를 살펴보겠습니다.

class Person (var name:String = "개발자", var age:Int = "20")

val p0 = Person() // name="개발자", age=20
val p1 = Person("김철수") // name="김철수", age=20
val p2 = Person("김영희", 25) // name="김영희", age=25
val p3 = Person(age=30, name="도라에몽") // name="도라에몽", age=30

어떤가요? 아래 p0~4 의 사용 방법과 주석만 봐도 어떤 의미인지 아시겠죠? 그래도 친절히 설명해보도록 하겠습니다.

우선 class 선언이 간결하게 바뀌었습니다. 변경 사항과 그 이유는 아래와 같습니다.

 

  1. 클래스 맴버 프로퍼티 선언이 생성자 파라미터로 이동했습니다.

    생성자 파라미터 앞에 var/val 를 선언하면 해당 파라미터가 클래스의 맴버 프로퍼티로 선언되며, 파라미터에 전달된 값으로 초기화 됩니다.

  2. 생성자(constructor) 오버로드 코드가 사라졌습니다.

    기본 값(default value)를 설정함으로써, 생성자의 파라미터로 값을 전달하지 않는 경우 기본 값으로 초기화 되므로 기존 생성자 오버로드가 필요 없습니다.

여기서 p3에 대해 추가적으로 설명을 드리자면, 함수 호출 시 해당 함수의 파라미터 이름을 명시하고 값을 선언하면 파라미터 순서와 관계없이 해당 파라미터에 값이 설정됩니다.

 

파라미터 기본 값 이라는 기능 하나로 정말 많은 양의 상용구 코드(Boilerplate Code)가 사라졌습니다. 놀랍지 않나요?

 

#4> 자바 스타일과의 비교

지금까지 만든 Person Class 선언을 자바 스타일과 비교해보겠습니다. 얼마나 많은 코드가 사라졌는지 눈으로 확인해보시죠.

// Java Style
public class Person {
  private String name = "개발자";
  private int age = 20;

  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  public Person(int age, String name) {
    this.name = name;
    this.age = age;
  }

  public Person(String name) {
    this.name = name;
  }

  public Person(int age) {
    this.age;
  }
}

// Kotiln Style
class Person(var name:String = "개발자", var age:Int = 20)

 

어떤가요? 정말 편리하죠? 하지만 벌써 놀라기는 이릅니다. 코틀린은 상용구 코드를 줄여주는 다양한 문법들을 지원합니다. 이 내용들은 앞으로의 포스팅에서 하나씩 풀어가도록 하겠습니다.

 

#5> 마치며

이번 포스팅에서는 Person이라는 이름을 가진 자바빈즈 클래스를 만들어봤습니다. 하지만 자바빈즈 규약에서는 클래스의 프로퍼티가 관례(convertion)를 따르는 getter와 setter를 구현해야 한다고 명시하고 있습니다. 위에서 작성한 클래스에는 개터와 세터가 없는데 자바빈즈라니 어떻게 된 일일까요?

 

결론부터 말씀드리면 지금까지 작성한 Person 클래스는 자바빈즈 규약을 정확히 따르고 있습니다. 그 이유에 대해서는 다음 포스팅 주제인 코틀린의 프로퍼티 편에서 이야기합니다.

 


 

하트와 구독, 그리고 광고 클릭은 포스팅 제작에 큰 도움이 됩니다.
댓글