#Private attribute example
class C {
has $!w; #private attribute
multi method w { $!w } #getter method
multi method w ( $_ ) { #setter method
warn “Don’t go changing my w!”; #some side action
$!w = $_
}
}
my $c = C.new
$c.w( 42 )
say $c.w #prints 42
$c.w: 43
say $c.w #prints 43
#but not
$c.w = 44
Cannot modify an immutable Int (43)
지금까지는 합리적이며
#Public attribute example
class C {
has $.v is rw #public attribute with automatic accessors
}
my $c = C.new
$c.v = 42
say $c.v #prints 42
#but not
$c.v( 43 ) #or $c.v: 43
Too many positionals passed; expected 1 argument but got 2
나는 ‘=’할당의 즉각적인 것을 좋아하지만 다중 방법이 제공하는 부수적 인 행동으로 번지가 쉬워야합니다. 나는 이것이 서로 다른 두 세계이며 혼합되어 있지 않다는 것을 이해합니다.
그러나 나는 왜 그냥 갈 수 없는지 이해하지 못한다 $ cv (43) public 속성을 설정하려면
- raku는이 두 가지 모드를 혼합하지 말라고 지시합니다. 일부 속성은 개인 속성과 일부 속성은 압력이 방법 방법에 대한 압력입니다 (일부 : 결장의 설탕)-이것이 Raku 디자인의 의도입니까?
- 뭔가 빠졌습니까?
답변
이것이 Raku 디자인의 의도입니까?
Raku 가이 분야에서 완전히 분류되지 않은 것은 아닙니다. 귀하의 질문은 Raku 디자인의 두 가지 주제에 대해 다루며, 둘 다 약간의 토론 가치가 있습니다.
라쿠는 일류 l- 값을 가지고 있습니다
라쿠는 일류가되는 l- 값을 충분히 활용합니다. 우리가 쓸 때 :
has $.x is rw;
생성되는 방법은 다음과 같습니다.
method x() is rw { $!x }
is rw
여기에는 메소드가 반환을 나타냅니다 리터 값 이다,에 할당 할 수있는 뭔가를 -. 따라서 우리가 쓸 때 :
$obj.x = 42;
이것은 구문 설탕이 아닙니다. 실제로 메소드 호출이며 할당 연산자가 그 결과에 적용됩니다. 메서드 호출은 Scalar
속성 의 컨테이너를 반환하고 할당 할 수 있기 때문에 문제가되지 않습니다 . 바인딩을 사용하여 이것을 두 단계로 나누면 사소한 구문 변환이 아닌 것을 알 수 있습니다. 예를 들면 다음과 같습니다.
my $target := $obj.x;
$target = 42;
객체 속성에 할당됩니다. 이 같은 메커니즘은 목록 할당을 포함하여 수많은 다른 기능 뒤에 있습니다. 예를 들면 다음과 같습니다.
($x, $y) = "foo", "bar";
List
컨테이너를 포함하는 컨테이너 를 구성하여 작동 $x
하며 $y
,이 경우 대입 연산자는 각면을 쌍으로 반복하여 대입을 수행합니다. 이것은 우리가 rw
그곳에서 객체 접근자를 사용할 수 있다는 것을 의미 합니다 :
($obj.x, $obj.y) = "foo", "bar";
그리고 그것은 모두 자연스럽게 작동합니다. 이것은 또한 배열과 해시 조각에 할당하는 메커니즘입니다.
또한 Proxy
읽기 및 쓰기 동작이 사용자의 통제하에있는 l- 값 컨테이너를 만들기 위해 사용할 수 있습니다 . 따라서 부작용을에 넣을 수 STORE
있습니다. 하나…
Raku는 “세터”보다 의미 론적 방법을 권장합니다
OO를 설명 할 때 “캡슐화”및 “데이터 숨기기”와 같은 용어가 종종 나타납니다. 여기서 핵심 아이디어는 객체 내부의 상태 모델, 즉 동작 (메서드)을 구현하기 위해 필요한 데이터를 표시하도록 선택하는 방식과 같이 새로운 요구 사항을 처리하기 위해 자유롭게 진화 할 수 있다는 것입니다. 물체가 복잡할수록 더욱 자유 로워집니다.
그러나 게터와 세터는 상태와 암시 적으로 연결된 메서드입니다. 상태에 직접 액세스하지 않고 메소드를 호출하기 때문에 데이터 숨기기를 달성한다고 주장 할 수 있지만 내 경험은 외부 코드가 일련의 setter 호출을 수행하여 작업을 수행하는 위치에서 빠르게 끝나는 것입니다. 기능 부러워 안티 패턴의 형태. 그리고 우리가 그렇게 한다면 , getter와 setter 연산을 혼합하여 연산을 수행하는 객체 외부의 논리로 끝날 것입니다. 실제로 이러한 작업은 수행중인 작업을 설명하는 이름을 가진 방법으로 노출되어야합니다. 우리가 동시 설정에 있다면 더욱 중요합니다. 잘 설계된 객체는 종종 메소드 경계에서 보호하기가 상당히 쉽습니다.
즉, 많은 용도 class
는 실제로 레코드 / 제품 유형입니다. 단순히 여러 데이터 항목을 그룹화하기 위해 존재합니다. .
시길이 접근자를 생성 할뿐만 아니라 다음과 같은 경우도 우연 이 아닙니다.
- 속성을 기본 객체 초기화 로직 (즉,
class Point { has $.x; has $.y; }
로 인스턴스화 할 수 있음Point.new(x => 1, y => 2)
)에 의해 설정되도록 선택하고.raku
덤프 메소드 에서 속성을 렌더링합니다 . - 속성을 기본
.Capture
객체로 선택합니다. 즉,이를 파괴 (예 :)에서 사용할 수 있습니다sub translated(Point (:$x, :$y)) { ... }
.
보다 절차 적이거나 기능적인 스타일로 작성 class
하고 레코드 유형을 정의하는 수단으로 사용하려는 경우 원하는 것 입니다.
Raku 디자인은 세터에서 영리한 작업을 수행하는 데 최적화되어 있지 않습니다. 최적화하기 어려운 것으로 간주되기 때문입니다. 레코드 유형에 필요한 것 이상입니다. 일부 언어에서는 할당 된 내용에 대한 유효성 검사를 원한다고 주장 할 수 있지만 Raku subset
에서는 해당 유형으로 전환 할 수 있습니다 . 동시에 우리가 실제로 OO 디자인을하고 있다면, getter / setter와 관련하여 생각하지 않고 상태 모델을 숨기는 의미있는 행동의 API가 필요합니다. 어쨌든 OO를 수행하는 데있어 중요한 부분 인 데이터와 행동.
답변
그러나 나는 왜 그냥 갈 수 없는지 이해하지 못한다 $ cv (43) public 속성을 설정하려면
글쎄, 그것은 건축가에게 달려 있습니다. 그러나 진지하게, 그것은 단순히 Raku가 작동하는 표준 방식이 아닙니다.
이제, 만들 전적으로 가능할 것이다 Attribute
모듈 공간, 같은의 특성 is settable
다른 접근 방법을 만드는 것, 할 값을 설정하는 하나의 값을 수락합니다. 코어 에서이 작업을 수행 할 때의 문제는 세계에 기본적으로 그러한 뮤 테이터의 반환 값에 대해 2 개의 캠프가 있다고 생각한다는 것입니다. 새로운 값 또는 이전 값을 반환 합니까?
모듈 공간에서 이러한 특성을 구현하려면 저에게 연락하십시오.
답변
나는 현재 당신이 혼란스러워 한 것 같습니다. 1 그 문제를 다루기 전에 혼란스럽지 않은 부분부터 다시 시작하겠습니다.
나는
=
과제 의 즉시 성을 좋아 하지만 여러 방법이 제공하는 부수적 인 행동으로 번지가 쉬워야합니다. 난 그냥 갈 수없는 이유 … 이해가 안$c.v( 43 )
공용 속성을 설정하려면
이 모든 것을 할 수 있습니다 . 즉 =
, 다음과 같은 경우 할당과 다중 방법을 사용하고 동시에 “그냥 가십시오 $c.v( 43 )
“라고 말합니다.
class C {
has $!v;
multi method v is rw { $!v }
multi method v ( :$trace! ) is rw { say 'trace'; $!v }
multi method v ( $new-value ) { say 'new-value'; $!v = $new-value }
}
my $c = C.new;
$c.v = 41;
say $c.v; # 41
$c.v(:trace) = 42; # trace
say $c.v; # 42
$c.v(43); # new-value
say $c.v; # 43
혼란의 가능한 소스 1
배후에서 다음 has $.foo is rw
과 같은 행을 따라 속성과 단일 메소드를 생성합니다.
has $!foo;
method foo () is rw { $!foo }
위의 내용은 정확하지 않습니다. 우리가보고있는 행동을 고려할 때, 컴파일러의 자동 생성 된 foo
메소드는 어떻게 든 같은 이름의 새로운 메소드가 자동으로 섀도 잉 하는 방식으로 선언되고 있습니다. 2
따라서 속성과 이름이 같은 하나 이상의 사용자 정의 메소드 를 원할 경우, 일반적으로 담당하는 동작을 유지하려면 자동으로 생성 된 메소드를 수동으로 복제 해야합니다 .
각주
1 비공개 vs 공개 게터 / 세터에 대한 Raku의 의견과 공개 게터 / 세터를 선언 할 때 뒤에서하는 일 (즉, write has $.foo
) 에 대한 명확하고 철저하고 권위있는 설명은 jnthn의 답변을 참조하십시오 .
2 속성에 대해 자동 생성 된 접근 자 메서드가 선언 된 only
경우 Raku는 동일한 이름의 메서드가 선언 된 경우 예외를 throw한다고 가정합니다. 선언 된 multi
경우, 새 메소드도 선언 된 경우에는 그림자로 표시하지 않아야하며 multi
그렇지 않은 경우 예외를 발생시켜야합니다. 따라서 자동 생성 접근자는 자동 섀도 잉을 허용하는 방식 으로 선언되지 only
않고 multi
대신 선언됩니다 .