2013-04-18 2 views
4

어떻게 Lisp에서 다음 Java 코드를 표현하겠습니까?CLOS의 생성자와 동일한 것은 무엇입니까?

리스프에서
class Foo { 
    private String s; 

    public Foo(String s) { 
     this.s = s; 
    } 
} 

class Bar extends Foo { 
    public Bar(int i) { 
     super(Integer.toString(i)); 
    } 
} 

make-instance 또는 initialize-instance 생성자의 상당? 그렇다면 슈퍼 클래스 생성자를 어떻게 호출합니까?

답변

13

CALL-NEXT-METHOD을 사용하여 다음 전화를 걸 수 있습니다.

일반적으로 표준 방법 조합 기능을 사용하고 INITIALIZE-INSTANCE:BEFORE, :AFTER 또는 :AROUND 방법을 씁니다.

한 가지 방법 :

(defclass foo() 
    ((s :type string :initarg :s))) 

(defclass bar (foo)()) 

(defmethod initialize-instance :around ((b bar) &key i) 
    (call-next-method b :s (princ-to-string i))) 

예 : 나는에 전달 인수를 변경하지 않고 CALL-NEXT-METHOD라고했습니다

CL-USER 17 > (make-instance 'bar :i 10) 
#<BAR 402000B95B> 

CL-USER 18 > (describe *) 

#<BAR 4130439703> is a BAR 
S  "10" 

참고. 방금 &key initarg 매개 변수를 변경했습니다.

+0

CALL-NEXT-METHOD는 같은 인수로 다음 메소드를 호출하지 않습니다. 예제를 구현하려면 어떻게해야합니까? 즉 정수 인수를 문자열로 변환하여 수퍼 클래스 메서드에 전달하는 방법은 무엇입니까? –

+0

@Tobias Brandt : 내 사례보기 –

2

다음은 작은 꼬임을 추가 한 Rainier의 예제를 증폭 한 것입니다. 적어도 구성 시간에 슬롯 값을 제한하여 전문화 (서브 클래 싱). 두 차원 사각형에 대한 클래스, 미터 박스을 고려 :

(defclass m-box() 
    ((left :accessor m-box-left :initform 0 :type integer :initarg :left ) 
    (top :accessor m-box-top :initform 0 :type integer :initarg :top ) 
    (width :accessor m-box-width :initform 0 :type integer :initarg :width) 
    (height :accessor m-box-height :initform 0 :type integer :initarg :height))) 

우리는 이런 식으로 시도 할 수 있습니다 : 미터 블록을 보자

(describe (make-instance 'm-box :left 42 :top -39 :width 5 :height 11)) 

: #<M-BOX {10047A8F83}> 
: [standard-object] 
: 
: Slots with :INSTANCE allocation: 
: LEFT = 42 
: TOP  = -39 
: WIDTH = 5 
: HEIGHT = 11 

지금 서브 클래스 또는 전문성을 고려은 단위 넓이와 높이가 인 상자입니다. 우리 미터 블록의 인스턴스를 만들 수

(defclass m-block (m-box)()) 
(defmethod initialize-instance 
    :around 
    ((mb m-block) 
    &key (left 0) (top 0)) 
    (call-next-method mb :left left :top top :width 1 :height 1)) 

: 가기 아니지만 높이 남아 위해 우리 값을 통과 할 초기화 인스턴스를 방법을 설정할은 다음과 같습니다.

(describe (make-instance 'm-block :left 17 :top -34 :width 5 :height 11)) 

: #<M-BLOCK {10049C0CC3}> 
: [standard-object] 
: 
: Slots with :INSTANCE allocation: 
: LEFT = 17 
: TOP  = -34 
: WIDTH = 1 
: HEIGHT = 1 

생성자는 그것은 어떤 존재하지 않는 슬롯을하는 것처럼 높이, 을 설정할 수있는 사용자의 시도를 차단 :

(describe (make-instance 'm-block :left 17 :top -34 :plugh 2345)) 

Invalid initialization argument: 
    :PLUGH 
in call for class #<STANDARD-CLASS COMMON-LISP-USER::M-BLOCK>. 
    [Condition of type SB-PCL::INITARG-ERROR] 

하지만을 수행 생성자가 1 사용자의 잘못된 입력을 수정합니다.

당신은 잘못된 입력 또는 높이에 사용자 시도하는 경우 error를 호출하여 모델보다 방수 수 있도록 할 수 있습니다 :

(defclass m-block (m-box)()) 
(defmethod initialize-instance 
    :around 
    ((mb m-block) 
    &key (left 0) (top 0) (width 1) (height 1)) 
    (when (or (/= 1 width) (/= 1 height)) 
    (error "an m-block must have unit width and height")) 
    (call-next-method mb :left left :top top :width 1 :height 1)) 

사용자가 다음 시도가 거부됩니다 :

(describe (make-instance 'm-block :left 17 :top -34 :width 5 :height 11)) 

an m-block must have unit width and height 
    [Condition of type SIMPLE-ERROR] 

이 기본값은 높이의 기본값을 보여줍니다.

(describe (make-instance 'm-block :left 17 :top -34 :width 1)) 

: #<M-BLOCK {1005377983}> 
: [standard-object] 
: 
: Slots with :INSTANCE allocation: 
: LEFT = 17 
: TOP  = -34 
: WIDTH = 1 
: HEIGHT = 1 

이 예 setf에 사용자 이후 폭 또는 높이를 허용 : 통해는 간다. 나는 너비와 높이를 만드는 법을 알고 있지 않다 서브 클래스 의 인스턴스에서는 읽기 전용인데 슈퍼 클래스의 인스턴스에서는 읽기 전용이 아니다.

관련 문제