CS 535 Object-Oriented Programming Spring Semester, 2003 Classes Part 2 |
||
---|---|---|
© 2003, All Rights Reserved, SDSU & Roger Whitney San Diego State University -- This page last updated 28-Jan-03 |
VisualWorks Menu Shortcut
Objects & Classes - Smalltalk Language Details
Items to cover:
Class names
Methods
Class Names
Smalltalk class names:
Simple Superclass Name
Superclass names
Qualified Subclass Name
Class Names & Namespaces
Classes are defined in a namespace
Allows classes in different namespaces to use the same name
Full name of a class includes namespace
Point Name Example
Each of the following is legal code in a workspace
Root.Smalltalk.Core.Point x: 1 y: 1. Smalltalk.Core.Point x: 1 y: 1. Core.Point x: 1 y: 1. Point x: 1 y: 1.
Methods
All methods are public
Methods considered private are placed in the method category called "private"
All methods return a value
Instance methods
Sent to instances of Classes
Examples
Class methods
Sent to Classes
Can not be sent directly to instance of the class
Commonly used to create instances of the class
Examples
Variables
Types of Variables
Named Instance Variable
Each object has its own copy of a named instance variable
Like
Example
Smalltalk.Core defineClass: #Point superclass: #{Core.ArithmeticValue} indexedType: #none private: false instanceVariableNames: 'x y ' classInstanceVariableNames: '' imports: '' category: 'Graphics-Geometry'
x & y are instance variables
| a b | a := Point x: 1 y: 4. b := Point x: -1 y: 2.We now have two point objects. Each point object has a local copy of x and y. Values in the local copies are different.
Accessing Instance variables in an Instance method Point instance method example
Point>>dotProduct: aPoint ^(x* aPoint x) + (y * aPoint y)
Adding an Instance Variables to a Class
To add an instance variable to a class,
Add the variable name in the string argument of instanceVariableNames:
Example
Smalltalk.Core defineClass: #Point superclass: #{Core.ArithmeticValue} indexedType: #none private: false instanceVariableNames: 'x y z ' classInstanceVariableNames: '' imports: '' category: 'Graphics-Geometry'
Removing an Instance Variables to a Class
Remove the variable name from the class definition
Make sure no methods still use the variable
Class Instance Variable
Smalltalk.Core defineClass: #ClassInstanceVariableExample superclass: #{Core.Object} indexedType: #none private: false instanceVariableNames: '' classInstanceVariableNames: 'test ' imports: '' category: 'As yet unclassified'
ClassInstanceVariableExample class>>test test isNil ifTrue:[ test := 0]. test := test + 1. ^test
Smalltalk.Core defineClass: #ClassInstanceVariableChild superclass: #{Core.ClassInstanceVariableExample} indexedType: #none private: false instanceVariableNames: '' classInstanceVariableNames: '' imports: '' category: 'As yet unclassified'
The Test ClassInstanceVariableExample test. Transcript print: ClassInstanceVariableExample test; cr; print: ClassInstanceVariableChild test; cr; flushOutput in Transcript 2
1
Shared Variables
Only one copy exists of each shared variable
Multiple classes and object can access the same shared variable
Adding a Shared Variable to a Class
In a browser select an existing class.
Click on the "shared variables" radio button in the browser
Now use the "Protocol" menu to add a new category for the shared variables
You get the template
SharedVariableClass defineSharedVariable: #NameOfBinding private: false constant: false category: 'accessing' initializer: 'Array new: 5'Change NameOfBinding to the name of the variable
Keep the "#" before the name
Change the other values as appropriate
Private and Public Shared Variables
A shared variable can be accessed from any class
Private shared variable access
Example Smalltalk.Core defineClass: #SharedVariableExample superclass: #{Core.Object} indexedType: #none private: false instanceVariableNames: '' classInstanceVariableNames: '' imports: '' category: 'Course-Examples'
Core.SharedVariableExample defineSharedVariable: #PublicVariable private: false constant: false category: 'data' initializer: '3'
Core.SharedVariableExample defineSharedVariable: #PrivateVariable private: true constant: false category: 'data' initializer: '5'
SharedVariableExample Instance Methods
privateVariable ^PrivateVariable
privateVariable: anObject PrivateVariable := anObject
publicVariable ^PublicVariable
publicVariable: anObject PublicVariable := anObject
Subclass Accessing Shared Variables
Smalltalk.Core defineClass: #SharedVariableChild superclass: #{Core.SharedVariableExample} indexedType: #none private: false instanceVariableNames: '' classInstanceVariableNames: '' imports: '' category: 'Course-Examples'
Core.SharedVariableChild methodsFor: 'accessing'
childPublic ^PublicVariable
childPrivate "Subclass can not use short name on private" ^Core.SharedVariableExample.PrivateVariable
Other Class Accessing Shared Variables
Smalltalk.Core defineClass: #SharedVariableUser superclass: #{Core.Object} indexedType: #none private: false instanceVariableNames: '' classInstanceVariableNames: '' imports: ' Core.SharedVariableExample.* ' category: 'Course-Examples' Core.SharedVariableUser methodsFor: 'accessing' privateVariable "Can not use short name on private variables" ^Core.SharedVariableExample.PrivateVariable publicVariable ^PublicVariable
Initializing Shared Variables
Core.SharedVariableExample defineSharedVariable: #PublicVariable private: false constant: false category: 'data' initializer: '3'
Shared variables have an initializer
The initializer by:
Constant Verses Non-Constant Shared Variables
A constant shared variable's value:
Some Existing Uses of Shared Variables
Transcript
A shared variable
An object that writes to a window
Character Constants
Where are tab, space, cr, lf defined?
Solution one - Class methods of Character
Indexed Instance Variable
Provides slots in objects for array like indexing
Used for Arrays
I have never added indexed instance variables
I have always used existing collection classes
Adding Indexed Instance Variables to a Class
Create a class using Class:Add Class:Indexed menu item in the browser.
You get the template somewhat like:
Core defineClass: #NameOfClass superclass: #{NameOfSuperclass} indexedType: #objects private: false instanceVariableNames: 'instVarName1 instVarName2' classInstanceVariableNames: '' imports: '' category: 'Course-Examples'
For this example I edited the template to be:
Core defineClass: #IndexedExample superclass: #{Core.Object} indexedType: #objects private: false instanceVariableNames: '' classInstanceVariableNames: '' imports: '' category: 'Course-Examples'
Once this is saved the following works:
| a | a := IndexedExample new: 10. a at: 1 put: 2. ^a
Inheritance
Smalltalk supports only single inheritance
Class "Object"
Inheritance and Name Clashes
Subclass can implement methods with same name as parent
This is called overloading the method
When message is sent to instance of the subclass, the subclass method is used
Subclass can not overload variable names
Special or PseudoVariables
self
Self, Super Example
Three classes to study self & super: Parent, Child, GrandChild
Parent
Smalltalk.Core defineClass: #Parent superclass: #{Core.Object} indexedType: #none private: false instanceVariableNames: '' classInstanceVariableNames: '' imports: '' category: 'Course-Examples'
Instance Methods
name ^'Parent'
Child Smalltalk.Core defineClass: #Child superclass: #{Core.Parent} indexedType: #none private: false instanceVariableNames: '' classInstanceVariableNames: '' imports: '' category: 'Course-Examples'Instance Methods name ^'Child' selfName ^self name superName ^super name
GrandChild Smalltalk.Core defineClass: #GrandChild superclass: #{Core.Child} indexedType: #none private: false instanceVariableNames: '' classInstanceVariableNames: '' imports: '' category: 'Course-Examples'GrandChild Instance Methods name ^'GrandChild'
Self, Super Example - ContinuedTest Program
| grandchild | |
Output In Transcript |
grandchild := Grandchild new. |
|
Transcript |
|
show: grandchild name; |
Grandchild |
cr; |
|
show: grandchild selfName; |
Grandchild |
cr; |
|
show: grandchild superName; |
Parent |
cr. |
|
Self, Super Example - ContinuedHow does this Work?
grandchild selfName
Why Super
Super is used when:
The child class extends the behavior of the inherited method
That is:
Why doesn't super refer to parent class of the receiver?
Object subclass #Parent name ^'Parent' Parent subclass #Child name ^super name , 'Child' Child subclass #Grandchild "No methods in Grandchild"
Sample Program | trouble | trouble := Grandchild new. trouble name.
Assume that super did refer to the parent class of the receiver. Sending the message "name" to trouble would call the code "super name , 'Child' ". The super would refer to the parent class of the receiver. Since the receiver is a Grandchild object, "super name" would refer to the "name" method in the Parent class. Hence the method will call itself with no way to end.
Implicit Return Values
If a method does not explicitly return a value, self is returned
Hence a method like:
decrease count ifNil: [count := 0]. count := count - 1
Is really:
decrease count ifNil: [count := 0]. count := count - 1. ^self
Style Issue - When to explicitly return?
Only explicitly return a value from a method when the intent of the method is to return a value. An explicit return indicates to other programmers that the intent of the method is to compute some return value. The intent of the decrease method is to change the state of the receiver. Hence it should not have a value explicitly returned.
Initializing Instance Variables
If the instance variables always start at same value:
Smalltalk.Core defineClass: #Counter superclass: #{Core.Object} indexedType: #none private: false instanceVariableNames: 'count ' classInstanceVariableNames: '' imports: '' category: 'Course-Examples'
Category: initialize
initialize count := 0Category: access
count ^count decrease count := count - 1 increase count := count + 1
new ^super new initialize
Example - Instance Creation with Parameters
Smalltalk.CS535 defineClass: #Counter superclass: #{Core.Object} indexedType: #none private: false instanceVariableNames: 'count ' classInstanceVariableNames: '' imports: '' category: 'Course-Examples'Instance Methods Category: initialize
setCount: anInteger count := anIntegerCategory: access
count ^count decrease count := count - 1 increase count := count + 1
Example - Instance Creation with Parameters ContinuedClass Methods
Category: instance creation
new ^self count: 0 count: anInteger ^super new setCount: anInteger
Category: examples
example "Counter example" "or one can use self example" | a | a := Counter new. a increase; increase. ^a count
Class Methods that Create Instances
Some Guidelines [1]
Smalltalk does not have constructors like C++/Java
Use class methods to create instances
Place these class methods in "instance creation" category
Initial State of Instances
Create objects in some well-formed state
Class creation methods should:
Beck's First Rule of Good Style [2]
"In a program written with good style,
everything is said once and only once"
Some violations of the rule:
new ^self count: 0 count: anInteger ^super new setCount: anInteger
new ^super new setCount: 0 count: anInteger ^super new setCount: anInteger
Providing Examples in Class Methods
A common Smalltalk practice is to provide
example "Counter example" | a | a := Counter new. a increase; increase. ^a count
[1] See Beck 1997, Constructor Method and Constructor Parameter Method patterns, pp. 21-24 and Johnson's class notes on Smalltalk Coding Standards
[2] See Beck 1997, page 6
Copyright ©, All rights reserved.
2003 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
OpenContent license defines the copyright on this document.
Previous    visitors since 28-Jan-03    Next