Classes & Instances

In the System Browser, select a package, and the code pane shows a class template.

13.1 Defining a class (Pharo fluid syntax)

In the System Browser, select a package, and the code pane shows a class template. Edit it and accept (Ctrl+S):

Object << #BankAccount — superclass << class name.

slots: — instance variables (Pharo calls them slots; they are first-class objects).

tag: — an optional sub-grouping inside the package (shown as a folder in the browser).

package: — the package that owns the class.

Other optional keywords: sharedVariables: (class variables), sharedPools:, traits:, layout: (e.g., VariableLayout, ByteLayout), and comment: is set separately via the comment pane.

When you evaluate a fluid definition from a Playground rather than accepting it in the browser, send install to the builder to actually create the class:

Object << #BankAccount
    slots: { #owner . #balance };
    tag: 'Model';
    package: 'Bank-Core'
(Object << #BankAccount
    slots: { #owner . #balance };
    package: 'Bank-Core') install.

13.2 Older (classic) syntax

Pharo 11 and earlier — and Squeak, Cuis, VisualWorks, VA Smalltalk, GemStone — use a keyword message to the superclass:

Pharo still understands the classic message, so old scripts keep working. GNU Smalltalk uses a bracket syntax (Chapter 41).

"Pharo ≤ 11"
Object subclass: #BankAccount
    instanceVariableNames: 'owner balance'
    classVariableNames: ''
    package: 'Bank-Core'

"Squeak / Cuis / classic Smalltalk-80"
Object subclass: #BankAccount
    instanceVariableNames: 'owner balance'
    classVariableNames: ''
    poolDictionaries: ''
    category: 'Bank-Core'

13.3 Writing methods

In the browser, select the class, a protocol (e.g., *accessing*), and type a method in the code pane; accept with Ctrl+S. In text, methods are shown as ClassName >> selector:

The first line is the message pattern (selector and argument names).

A method without an explicit ^ returns self.

Instance variables are visible only inside the object's methods — encapsulation is total: other objects must send messages.

BankAccount >> initialize
    super initialize.
    balance := 0

BankAccount >> owner
    ^ owner

BankAccount >> owner: aString
    owner := aString

BankAccount >> balance
    ^ balance

BankAccount >> deposit: anAmount
    anAmount <= 0 ifTrue: [ ^ self error: 'Deposit must be positive' ].
    balance := balance + anAmount

BankAccount >> withdraw: anAmount
    anAmount > balance ifTrue: [ ^ self error: 'Insufficient funds' ].
    balance := balance - anAmount

13.4 Creating instances

In VisualWorks and some older dialects new does not call initialize; write a class-side new ^ super new initialize there.

| acct |
acct := BankAccount new.        "new allocates, then sends #initialize (Pharo, Squeak, Cuis, GNU 3.2+)"
acct owner: 'Ada'.
acct deposit: 100; withdraw: 30.
acct balance.                   "→ 70"

13.5 Class-side instance creation methods

Toggle to the class side in the browser and add constructors:

Use self new, not BankAccount new, so subclasses get instances of themselves.

BankAccount class >> owner: aString
    ^ self new
        owner: aString;
        yourself

BankAccount class >> owner: aString balance: anAmount
    ^ (self owner: aString) deposit: anAmount; yourself
(BankAccount owner: 'Grace' balance: 500) balance.    "→ 500"

13.6 Printing objects

Override printOn: to control how an object is displayed in inspectors, debuggers, and Print it:

printString calls printOn:; displayString (for end users) calls displayStringOn:; storeString produces source that rebuilds the object.

BankAccount >> printOn: aStream
    super printOn: aStream.              "→ 'a BankAccount'"
    aStream
        nextPutAll: '(';
        nextPutAll: owner asString;
        nextPutAll: ': ';
        print: balance;
        nextPutAll: ')'
(BankAccount owner: 'Ada' balance: 70) printString.   "→ 'a BankAccount(Ada: 70)'"

13.7 Equality and hashing

If you override =, you must override hash consistently, or Sets and Dictionaries will misbehave:

Object << #Money
    slots: { #amount . #currency };
    package: 'Bank-Core'

Money >> = other
    self == other ifTrue: [ ^ true ].
    self class = other class ifFalse: [ ^ false ].
    ^ amount = other amount and: [ currency = other currency ]

Money >> hash
    ^ amount hash bitXor: currency hash

13.8 Class comments

Every class has a comment (the *Comment* tab). Pharo's convention is CRC style: *I represent… My responsibility is… I collaborate with…*, followed by examples. Missing comments are flagged by the Quality Assistant.