객체 직렬화
객체 직렬화 (Object Serialization)
클래스의 인스턴스를 직렬화되도록 만들고 싶다면 define-serializable-class*나 define-serializable-class 폼을 사용하면 돼요. 이 폼들은 클래스를 만들면서 동시에 직렬화 지원 코드를 함께 정의해줘요. 외부화(externalize)·내부화(internalize) 메서드를 쓰는 방식과 완전 자동 방식, 두 가지 직렬화 경로가 있어요.
출처: Racket Reference
본문
syntax
(define-serializable-class* class-id superclass-expr
(interface-expr ...)
class-clause ...)
class-id를 클래스에 바인딩해요. superclass-expr, interface-exprs, class-clauses는 class*에서와 같아요.
이 폼은 모듈 안이든 밖이든 최상위 레벨에서만 사용할 수 있어요. class-id 식별자는 새 클래스에 바인딩되고, deserialize-info:class-id도 정의돼요. 정의가 모듈 안에 있으면 후자는 module+를 통해 deserialize-info 서브모듈에서 제공돼요.
클래스에 대한 직렬화는 두 가지 방식 중 하나로 동작해요:
-
클래스가 내장 인터페이스
externalizable<%>를 구현하면, 객체는externalize메서드를 호출해 직렬화돼요. 그 결과는 직렬화 가능한 무엇이든 될 수 있지만(당연히 객체 자신은 안 돼요), 직렬화 원본이 아닌 것이어야 해요. 역직렬화는 클래스의 인스턴스를 초기화 인자 없이 만들고,externalize의 결과로(더 정확히는 이전 호출의 직렬화된 결과를 역직렬화한 버전으로) 객체의internalize메서드를 호출해요.이 방식의 직렬화를 지원하려면 클래스가 초기화 인자 없이 인스턴스화될 수 있어야 해요. 또한 클래스의 인스턴스(그리고 그런 다른 클래스들)만 포함하는 순환은 직렬화할 수 없어요.
-
클래스가
externalizable<%>를 구현하지 않으면, 그 클래스의 모든 슈퍼클래스는 직렬화 가능하거나 투명(즉 inspector가#f)해야 해요. 직렬화와 역직렬화는 완전히 자동이며, 인스턴스의 순환을 포함할 수 있어요.인스턴스 순환을 지원하기 위해 역직렬화는 모든 필드가 정의되지 않은 값(uninitialized)인 상태로 클래스의 인스턴스를 만든 다음, 필드 값을 설정하도록 객체를 변형(mutate)할 수 있어요. 직렬화 지원이 달리 객체의 필드를 가변으로 만들지는 않아요.
두 번째 경우에서, 직렬화 가능한 서브클래스는 externalizable<%>를 구현할 수 있는데, 그러면 externalize 메서드가 모든 직렬화를 담당해요(즉 서브클래스의 인스턴스에 대해 자동 직렬화가 상실돼요). 첫 번째 경우에 모든 직렬화 가능한 서브클래스는 externalizable<%>를 구현해요. 서브클래스가 부모 클래스의 모든 인터페이스를 구현하기 때문이에요.
두 경우 모두, 객체가 (자체로 직렬화 가능하지 않은) 서브클래스의 직접 인스턴스라면, 그 객체는 직렬화 가능한 클래스의 직접 인스턴스인 것처럼 직렬화돼요. 특히 비직렬화 가능한 서브클래스의 인스턴스에 대해서는 externalize 메서드의 오버라이딩 선언이 무시돼요.
syntax
(define-serializable-class class-id superclass-expr
class-clause ...)
define-serializable-class*와 같지만 인터페이스 표현식이 없어요(class와 유사).
interface
externalizable<%> : interface?
externalizable<%> 인터페이스는 externalize와 internalize 메서드만 포함해요. 더 많은 정보는 define-serializable-class*를 참고하세요.
더 알아보기
- Object Equality and Hashing — 객체 동등성과 해싱.
- Object Printing — 객체 출력.