본문 바로가기
언어/Kotlin

Java와 비교하는 Kotlin - 코틀린의 클래스 종류

by 개발짜 2022. 11. 5.

데이터 클래스

데이터 클래스: data 키워드로 선언하며 자주 사용하는 데이터를 객체로 묶어준 클래스

 

// 데이터 클래스 선언
class NonDataClass(val name: String, val email:String, val age: Int)
data class DataClass(val name: String, val email: String, val age: Int)

fun main() {
	// 객체 생성
    val non1 = NonDataClass("data", "da@ta.com", 10)
    val non2 = NonDataClass("data", "da@ta.com", 10)
    
    val data1 = DataClass("data", "da@ta.com", 10)
    val data2 = DataClass("data", "da@ta.com", 10)
    
    // 객체의 데이터를 비교하는 equals
    println("non data class equals : ${non1.equals(non2)}")
    println("data class equals : ${data1.equals(data2)}")
}

[실행 결과]
non data class equals : false
data class equals : true
  • 데이터 클래스의 객체를 비교하면 객체의 데이터를 비교하므로  true 이다.
  • 데이터 클래스는 데이터를 다르는 데 편리한 기능을 제공한다.
  • 객체의 데이터를 비교할 때 이용하는 equals 함수는 주 생성자에 선언한 멤버 변수의 데이터만 비교 대상으로 삼는다.
  • 데이터 클래스의 toString() 함수는 객체가 포함하는 멤버 변수의 데이터를 출력한다.

오브젝트 클래스

오브젝트 클래스: 코틀린에서 익명 클래스를 만들 목적으로 사용

 

val obj = object {
    var data = 10
    fun some() {
        println("data : $data")
    }
}

fun main() {
    obj.data = 20 // 오류
    obj.some() // 오류
}
  • object 키워드로 클래스를 선언했지만 타입을 명시하지 않았으므로 이 객체는 코틀린의 최상위 타입인 Any로 취급한다. -> Any 타입 객체에 data, some() 함수를 선언했는데도 접근할 수 없다.

 

open class Super {
    open var data = 10
    open fun some() {
        println("i am super some() : $data")
    }
}

val obj = object: Super() {
    override var data = 20
    override fun some() {
        println("i am object some() : $data")
    }
}

fun main() {
    obj.data = 30 // 성공
    obj.some() // 성공
}

[실행 결과]
i am object some(): 30
  • obj가 Super() 클래스를 상속 받아 Super 클래스의 멤버에 접근할 수 있음

자바와 차이점

코틀린의 오브젝트 클래스와 유사하게 자바에는 익명 객체(클래스)가 있다.

익명 객체
  • 익명 객체는 단독으로 사용할 수 없고 클래스를 상속하거나 인터페이스를 구현해야 생성할 수 있다.
  • 필드, 로컬 변수의 초깃값, 매개 변수의 매개 값으로 사용한다.
  • UI 이벤트 처리 객체나 스레드 객체를 간편하게 생성할 목적으로 많이 사용한다.
  • 재사용이 불가능하고 1회성으로 사용한다.

 

익명 자식 객체 생성

부모클래스 [필드|변수] = new 부모클래스(매개값, ...) {
	// 필드
	// 메소드
	// 생성자는 가질 수 없다.
};
public class AnonymousEx {
	// 익명 자식 객체 생성시
	// 부모 클래스를 상속해서 중괄호 {} 의 내용과 같이 자식 클래스를 선언하라는 뜻. 
	// new 연산자는 이렇게 선언된 자식 클래스를 객체로 생성한다.
	Parent field = new Parent() { // 필드 선언시 초기값으로 익명 자식 객체를 생성해서 대입한것.
		int childField;
		
		// 부모 클래스의 메소드를 재정의 
		@Override
		void parentMethod() {
			
		}
		// 메소드 내에서 로컬 변수 선언시 초기값으로 익명 자식 객체를 생성해서 대입한당.
		void childMethod() {
			Parent localVar = new Parent() {
				int childField;
				@Override
				void parentMethod() {}
				
			};
		}
	};//익명 클래스의 선언은 하나의 실행문이므로 끝에 세미콜론(;)이 무조건 붙는다. (주의!!)
}
  • 익명 자식 객체에 새롭게 정의된 필드와 메서드는 익명 자식 객체 내부에서만 사용되고 외부에서는 필드와 메서드에 접근 할 수 없다.
  • 부모 타입의 변수에 대입되기 때문에 부모 타입에 선언된 것만 사용할 수 있기 때문이다.

 

익명 구현 객체 생성

인터페이스 [필드|변수] new 인터페이스() {
	// 인터페이스에 선언된 추상 메소드의 실체 메소드 선언
	// 필드
	// 메소드
};
public class AnonymousEx3 {
	RemoteControl field = new RemoteControl() {
		// 필드 초기값으로 대입
		
		@Override
		public void turnOn() {
			System.out.println("TV 켜기");
		}
		
		@Override
		public void turnOff() {
			System.out.println("TV 끄기");
		}
	}; // 세미콜론 잊지 말기 !
	void method() {
		// 로컬 변수 값으로 대입하기
		RemoteControl locVal = new RemoteControl() {
			
			@Override
			public void turnOn() {
				System.out.println("오디오 켜기");
			}
			
			@Override
			public void turnOff() {
				System.out.println("오디오 끄기");
			}
		};
		// 로컬 변수 사용하기
		locVal.turnOn();
	}
	void method2(RemoteControl rc) {
		rc.turnOn();
	}
}
  • 중괄호 {} 안에는 인터페이스에 선언된 모든 추상 메소드의 실체 메소드를 작성해야 한다

 

참고 - https://velog.io/@sezzzini/Java-%EC%9D%B5%EB%AA%85-%EA%B0%9D%EC%B2%B4


 

컴패니언 클래스

컴패니언 클래스: 멤버 변수나 함수를 클래스 이름으로 접근하고자 할 때 사용
class MyClass {
    companion object {
        var data = 10
        fun some() {
            println(data)
        }
    }
}

fun main() {
    MyClass.data = 20
    MyClass.some()
}
  • 클래스 이름으로 멤버에 바로 접근할 수 있음

자바와 차이점

public class Data {
    private static String data = "data";

    public static String getData() {
        return data;
    }
}

public class main {
    public static void main(String[] args) {
        System.out.println(Data.getData());
    }
}

[실행 결과]
data
  • 자바의 static 과 유사한 기능을 가짐
  • 클래스의 변수와 메서드에 static 으로 선언되어 있으면 클래스 이름으로 멤버에 바로 접근할 수 있다
  • 그러나 모든 멤버에 접근이 가능한 것은 아니다.

댓글