2014-10-03 5 views
1

저는 스몰 토크 (VisualAge 환경)에서 새로 왔으며 그녀의 인스턴스 개수를 세는 클래스를 만들려고합니다. 불행히도 '새로운'방법을 무시할 때 무언가 작동하지 않습니다.스몰 토크에서 클래스의 인스턴스를 만드는 방법은 무엇입니까?

Object subclass: #TestClassB 
    instanceVariableNames: 'niceVariable ' 
    classVariableNames: 'InstanceCounter ' 
    poolDictionaries: ''! 

!TestClassB class publicMethods ! 

initWithNiceParameter: parameter 

    |testClassBInstance| 

    testClassBInstance:= self new. 
    ^(testClassBInstance niceVariable: parameter)! 

new 
    super new. 
    InstanceCounter isNil 
     ifTrue: [InstanceCounter := 0] 
     ifFalse: [InstanceCounter := InstanceCounter + 1]. 
    ^self 
    ! ! 

!TestClassB publicMethods ! 

niceVariable: anObject 
    "Save the value of niceVariable." 
    niceVariable := anObject. 
! ! 

내가 'initWithNiceParameter'메시지와 함께 새로운 객체 생성하고 싶습니다 : 이것은 내 수업 코드

TestClassB initWithNiceParameter: 'my super string' 

을하지만 얻을 수있는 모든 오류입니다 :

TestClassB does not understand niceVariable: 

그것은 때문이다 'TestClassB'도 개체이며 'niceVariable'설정자가없는 것으로 보입니다.

'새'방법을 무시할 때 개체를 만드는 방법을 알고 있습니까?

답변

3

new 메서드 구현은 self을 반환합니다. self의 값은 new이 클래스 메서드이고 클래스 메서드에 self이 클래스 자체이기 때문에 TestClassB 클래스가 있습니다.

new 
    |instance| 
    instance := super new. 
    InstanceCounter isNil 
     ifTrue: [InstanceCounter := 0] 
     ifFalse: [InstanceCounter := InstanceCounter + 1]. 
    ^instance 

이하 :

new 
    InstanceCounter isNil 
     ifTrue: [InstanceCounter := 0] 
     ifFalse: [InstanceCounter := InstanceCounter + 1]. 
    ^super new 
+1

우리가 개선하는 동안, 클래스 측 # 초기화에서 InstanceCounter를 0으로 초기화하고 분기를 완전히 제거합시다. –

+0

'TestClassB allInstances size'가 충분하지 않습니까? –

+0

@SeanDeNigris # 초기화 및 분기 제거로 무엇을 의미합니까? 나는이 메소드를 만들었다. (#new와 같은 클래스 측 메소드이다.) Object 클래스에서 #initialize를 오버라이드하지만 새로운 객체를 생성하면 자동으로 호출되지 않는다. – user3452568

0

약간 OT하지만 #ifTrue :

당신은 super new을 전송하여 생성되었다 객체를 반환해야 ifFalse이 불필요하게 복잡하다. 클래스 레벨의 변수를 초기화하는 스몰 토크의 방법과 같이 * # 초기화 클래스 측에 있습니다

TestClassB class>>#initialize 
    InstanceCounter := 0 

당신이 시스템에 TestClassB를로드 할 때 지금, InstanceCounter이 초기화됩니다 당신이에 Johan's short version에서 단순화 할 수 있습니다 : #initialize 메소드가 자동으로 호출되는 경우 내가 아는하지 않았기 때문에

TestClassB class>>#new 
    InstanceCounter := InstanceCounter + 1. 
    ^super new 
  • 또는 느리게
+0

'TestClassB >> # new' 클래스의 메소드가 아니어야합니까? 이렇게 :'TestClassB class >> # new'? – user3452568

+0

하하 네 말이 맞아. 아주 좋아! 나는 위에서 복사 한 것을 복사합니다 ... –

0

나는 혼란스러워했다. 저는 VisualAge 7.5를 사용합니다. GUI를 사용하여 새 클래스를 작성한 다음 (마우스 오른쪽 단추로 클릭하고, "new"-> "part ...") 새 클래스를 저장하면 #initialize가 자동으로 호출되지 않습니다. 작업 공간에 클래스의 인스턴스를 작성하는 경우에도 마찬가지입니다. 그러나 클래스를 내 보낸 다음 다시로드하면 #initialize가 호출됩니다. 더 구체적으로 클래스 정의는 다음과 같습니다.

Object subclass: #InitTest 
    instanceVariableNames: '' 
    classVariableNames: '' 
    poolDictionaries: ''! 

!InitTest class publicMethods ! 

initialize 
Transcript show: 'initialize method'; cr.! 
new 
Transcript show: 'new method'; cr. 
^super new.! ! 

InitTest initialize! "<- it's created automatically" 
InitTest initializeAfterLoad! 

매우 까다로운 부분입니다. VisualAge 작업 공간에서 클래스 정의를로드 (다시)하여 #initialize가 호출되는지 확인하십시오 (작성하지 않고 InitTest 초기화)?

+0

Pharo에서 일반적인 방법은 클래스가 이미로드 된 경우'''InitTest initialize'''를 보내는 것입니다. 왜 그걸 피하고 싶어? 그것은 단지 개발의 용이성을위한 것입니다 ... –

+0

나는 지금 당신의 질문을 이해한다고 생각합니다. class-side #initialize는 클래스를로드 할 때 또는 명시 적으로 호출 할 때 호출됩니다. 인스턴스 측 #initialize는 클래스 측 #new에서 호출되어야합니다. Pharo에서는이 작업이 자동으로 수행되지만 다른 방언에서는 수행되지 않습니다. 자세한 내용은 http://stackoverflow.com/questions/5692844/difference-between-new-and-initialize-in-smalltalk를 참조하십시오. –

관련 문제