2016-08-20 3 views
2

나는 자주 다른 클래스의 목록으로 구성된 클래스가있다. 예를 들어 벡터로 구성된 벡터 목록 클래스를 갖게됩니다. 긴 문장을 쓰는 것을 피하기 위해, 나는 임베디드 클래스에 접근하기위한 메소드를 작성한다. 그러나이 메서드는 getter로만 작동합니다. 슬롯 값을 설정하는 데 사용할 수 없습니다. 메소드를 사용하여 클래스 슬롯 값을 설정하는 방법이 있습니까? 다음은 Common Lisp의 클래스에 대한 게터와 설정자

는 최소한의 예입니다

(defclass vector() 
    ((name :accessor vector-name 
     :initarg :name))) 

(defclass vector-list() 
    ((vectors :accessor vector-list-vectors 
      :initarg :vectors))) 

(defun make-vector-list() 
    (make-instance 'vector-list 
    :vectors (list 
       (make-instance 'vector :name 'v1) 
       (make-instance 'vector :name 'v2)))) 

(defmethod access-vector-name ((vt vector-list) vector-idx) 
    (vector-name (nth vector-idx (vector-list-vectors vt)))) 


;; returns V1 
(print (access-vector-name (make-vector-list) 0)) 

;; Now, trying to set the same slot returns an error 
;; How can I set the slot? 
(setf (access-vector-name (make-vector-list) 0) 'new); --> error 

답변

6

간단한 작성하는 것입니다 :

(setf (aref (access-vector-name ...) index) value)` 

을하지만 당신은 당신이 배열/벡터를 가지고 있다는 사실을 노출하지 않으려는 경우 사용자 정의 setf 확장자를 정의 할 수 있습니다.

먼저 access-vector-name을 클래스에 :reader으로 정의하십시오. 그런 다음 : 의도가 기본이되는 구현을 숨기는 것입니다

(defun (setf access-vector-name) (newval obj index) 
    (setf (aref (access-vector-name obj) index) newval)) 

경우, 어쩌면 access-vector-name 나쁜 이름입니다.

+1

대단히 감사합니다. – audrow

4

이렇게하려면 설정 메소드를 정의하면됩니다. 그러나 귀하의 코드는 그대로 유효하지 않습니다 : VECTORCL 패키지의 정의 된 심볼이며 실제로는 VECTOR이라는 클래스를 정의하는 것은 끔찍하게 불법입니다 (그리고 괜찮은 구현은이 경우 barf가됩니다) . 다음은 기본 클래스가 VEC으로 이름이 변경되고 setter 메서드가있는 코드의 버전입니다.

(defclass vec() 
    ;; Don't call it VECTOR since it's a function in CL 
    ((name :accessor vec-name 
     :initarg :name))) 

(defclass vec-list() 
    ((vecs :accessor vec-list-vecs 
     :initarg :vecs))) 

(defun make-vec-list() 
    (make-instance 'vec-list 
    :vecs (list 
      (make-instance 'vec :name 'v1) 
      (make-instance 'vec :name 'v2)))) 

(defmethod access-vec-name ((vt vec-list) vec-idx) 
    (vec-name (nth vec-idx (vec-list-vecs vt)))) 

(defmethod (setf access-vec-name) (new (vt vec-list) vec-idx) 
    (setf (vec-name (nth vec-idx (vec-list-vecs vt))) new)) 

CLOS이 같은 접근 방법을 정의하는 사전 정의 된 매크로가없는 외부 클래스 정의 : 잘 모르겠어요 왜하지만 정말이 같은 '순수한'접근의 경우는 상대적으로 드문 아마도 때문이다.

+1

글쎄, 기호가 다른 패키지에 속해 있다면 클래스라는 이름을 붙일 수는 있겠지만 ......... 니트 피킹이다. – coredump

+1

@coredump 그래, 내 생각 엔 내가 '사소한 패키지 설정'이 없다고 생각하고 있었다. ... – tfb

+0

고마, 고마워. – audrow

관련 문제