2016-06-12 2 views
2

Pharo 5.0을 사용하고 있습니다. 몇 가지 사례에서 기존 Pharo 클래스 (예 : , 예 :, DBXTalk/Garage 또는 Regex-Core의 무언가)에서 제한 또는 가능한 버그를 발견했습니다. 나는 자신의 프로젝트 밖에서 클래스에 존재하는 셀렉터 또는 셀렉터 세트를 수정하여 패키지의 일부로 만들 수 있기를 원합니다.다른 패키지의 클래스에서 기존 선택기를 재정의하는 방법

나는 외부 클래스의 새로운 선택기를 만들고 (이 tutorial 같이 예를 들어,) 내 패키지에 저를 이동하는 방법에 대한 몇 가지 지침을 발견했다. 아주 멋지다. 그러나 어떤 경우에는 실제로 외부 클래스의 기존 선택기를 수정하고 해당 셀렉터를 사용하면 외부 클래스의 셀렉터보다 우선합니다. 기존 타사 또는 Pharo 사전 제공 패키지를 수정하고 싶지 않습니다.

GNU 스몰 토크에서 나는 클래스 확장을하는 정상적인 부분처럼 그렇게 할 수 있습니다. 예 :

Kernel.MatchingRegexResults extend [ 
    at: anIndex [ 
     "My updated version of the 'official' Kernel.MatchingRegexResults#at: selector" 
     "This is part of my package so overrides the 'official' version" 
     ... 
    ] 

    foo [ 
     "My new foo selector" 
    ] 
] 

Pharo 5.0에서 어떻게해야합니까? 나는 꽤 많은 검색을 해왔지만 그것을 할 수있는 방법을 찾지 못했습니다. "확장"또는 "재정의"라는 단어는 예를 들어으로 삽입하면 Pharo 도서로 Pharo에 표시되지 않습니다.

+1

* Move to package ... * 명령을 시도 했습니까? 선택기 목록의 오른쪽 클릭 메뉴에서 사용할 수 있습니다. –

+0

@LeandroCaniglia 예 했어요. 사실, 나는 내 질문에 그것을 언급했다. 기존 외부 클래스에 대한 새 선택기를 만들어 내 새 선택기를 내 패키지로 옮기려는 경우이 작업이 효과적입니다. 그러나 그것은 기존 셀렉터의 구현을 내 패키지로 옮겨 외부 패키지에서 제거하기 때문에 기존 셀렉터를 수정/재정의하는 데는 효과가 없습니다. 재정의 된 selector를 외부 패키지에서 제거하고 싶지 않고 재정의하려고합니다. – lurker

+1

재정의 (override)는 재정의 (override)를 의미합니다 ... 메소드를 다시 작성하면 패키지로 옮겨 지지만 모든 시스템에 대해 변경됩니다. Pharo에는 모듈 시스템이 없으므로 동일한 클래스에서 동일한 이름을 가진 다른 메소드를 가질 수 없습니다. – EstebanLM

답변

2

Kernel.MatchingRegexResults extend [ 
    at: anIndex [ 
     "method body" 
    ] 
    foo [ 
     "My new foo selector" 
    ] 
] 

파일 브라우저에서 제기 될 수있는 Pharo 변경 세트에이

!MatchingRegexResults methodsFor: 'protocol'! 
at: anIndex 
    "method body" 
! 
foo 
    "My new foo selector" 
! ! 

과 같을 것이다 GNU 스몰 토크 구문의 코드.

그러나 GNU 스몰 토크와 Pharo Smalltalk 모두 실제로 해당 클래스의 원래 버전의 메소드를 대체하고 있습니다.

GNU 스몰 토크에서는 이미지 저장에 익숙하지 않으므로 확장 구문이 원래 클래스의 원래 메서드를 수정하지 않는다고 생각할 수 있습니다.

실제로 정확히 같습니다.

GNU 스몰 토크에서는 일반적으로 gst를 실행할 때마다 이전의 수정되지 않은 이미지로 시작합니다. 이것은 GNU 스몰 토크에서 이미지의 기본 위치가 일반 사용자에게 쓰기 가능하지 않기 때문입니다. 따라서 gst는 매번 동일한 읽기 전용 이미지를 읽고, 클래스 정의와 확장으로 메모리 내에서 수정하고, 수정 된 이미지는 프로그램이 실행되는 동안 일시적으로 만 존재하며 프로그램 종료시 삭제됩니다.

+0

변경 관리 관점에서 가정 할 때 가장 좋은 방법은 변경된 선택기를 패키지로 이동하는 것입니다. LeandroCaniglia는 기존 패키지의 수정을 의미한다고 할지라도 자신의 의견에서 이렇게 말합니다. 적어도 추적하기는 쉽습니다. 이 패키지를 공유하고 다른 사용자가 사용하려고하면 내 패키지의 수정 된 패키지가 표준 패키지의 패키지보다 우선합니다. 또는 그것은 단지 패키지가 그들의 환경에서 마지막으로 업데이트되었는지에 달려 있습니까? – lurker

+1

클래스에는 한 가지 버전의 메소드 만있을 수 있습니다. 가장 최근에로드 된 메소드 버전이 현재 버전이됩니다. 별표 표시된 프로토콜은 System Browser 및 Monticello Browser 용으로 다른 패키지의 확장 방법을 그룹화하는 역할 만합니다. 이 메소드는 패키지에 관계없이 동일한 클래스의 일부로 남아 있습니다. –

+0

맞습니다. 그러나 둘 이상의 패키지에서 정의 된 경우 어느 것이 "이기는가"? 패키지로드 순서에 따라 결정됩니까? 내 패키지 Y에서 셀렉터 정의 된 패키지 X를 재정의하면 Y 버전이이를 대체합니다. 그러나 이후에 패키지 X의 최신 버전을로드하면 선택기가 새 버전으로 대체되면 Y 버전이 실행됩니까? 또는 그냥 건너 뛰면 Y 패키지 버전이 남아 있습니까? – lurker

3

Milan Vavra가 작성한 것 외에도 *YourPackage-(something)이라는 프로토콜의 모든 메소드는 클래스가 속한 패키지에 관계없이 YourPackage 패키지에 속하게됩니다. 적어도 Squeak에서는 *YourPackage-override 프로토콜에 이와 같은 메서드를 재정의하는 규칙이 있습니다. 파로는 아마도 비슷한 명명 규칙을 가지고있을 것입니다. 패키지로 이동 기능을 사용하면 메서드가 "별표가 표시된"프로토콜로 이동합니다.

그러나 두 개의 패키지가 동일한 메소드에 대한 구현을 동시에 제공 할 수 없으므로 이러한 재정의를 사용하지 않는 것이 좋습니다.Monticello는 원본 메서드와 재정의 메서드를 모두 보존하려고 시도하지만 (원래의 PackageInfo>>isOverrideCategory:의 보낸 사람 참조) 원래 메서드에 대한 업데이트로 재정의 메서드를 재정의하거나 원래 메서드에 대한 업데이트를 놓칠 수 있습니다. .

"올바른 방법"은 원래 패키지의 원래 메서드를 리팩터링하여보다 쉽게 ​​사용자 지정할 수 있도록하는 것입니다.

+0

예, 이해합니다. 불행히도 필자가 요구하지만 작성하지 않은 패키지에는 버그가 있거나 기본 기능이 부족한 몇 가지 사례가 있습니다.이 경우 패키지를 수정하는 것이 아니라 해결 방법이 있습니다. 그렇게 할 때 쉽게 추적 할 수 있기를 원합니다. 한 가지 예가 [정규식 대체 문자열 캡처] (http://stackoverflow.com/questions/37403092/capture-string-in-regex-replacement) (개선 사항)입니다. 다른 하나는 DBXTalk/Garage에 있으며, 데이터베이스에서 정수 속성이 NULL 일 때 오류를 발생시킵니다 ('nil'을 반환해야합니다). – lurker

+0

물론, 단기간에 다른 메시지를 보내지 않으려는 경우 일반적으로 메시지가 표시되지 않습니다. 그러나 나는 또한 여기에 오는 다른 독자들을 위해 그것을 지적하고 싶었다. :-) – JayK

+0

실제로! 그것을 지적 주셔서 감사합니다. – lurker