2

I would like to create a smalltalk application with a class that has an instance variable that is an array and an instance variable that is the array's size. I would ideally like to initialise these when the object gets created but I have these manually being initialised in a method.

The following is my code:

Object subclass: Student [
    | numTests marks |


    initialize [
        numTests := 0.
        marks := Array new: 10.
    ]
]
student := Student new.
student initialize.

But I get the following error:

Object: Array new: 10 "<0x10b054b80>" error: method is responsibility of a subclass

How can I solve this problem?

Leandro Caniglia
  • 14,495
  • 4
  • 29
  • 51
Keagansed
  • 183
  • 1
  • 1
  • 13

1 Answers1

6

You may not really want to do this. I generally use Squeak derivatives and Array new: works but is often not what you want because Arrays are fixed size (i.e. you can't add or remove elements) and so you typically use something like OrderedCollection instead. Also, you generally don't want to store the size in an ivar but rather send #size to your collection whenever you need to know how many elements it contains.

I've modified your code example based on the above suggestions (also notice that you don't need to send #initialize explicitly, it's done for you via #new:):

Object subclass: Student [
    | marks |


    initialize [
        marks := OrderedCollection new: 10.
    ].

    addMark: newMark [
        marks add: newMark
    ].

    removeMarkAt: markIdx [
        marks removeAt: markIdx
    ].

    size [
        ^ marks size
    ]
]
student := Student new.

If you really need to create a fixed size array, please update the question with which Smalltalk variant you are using so that someone with specific knowledge of the implementation can help. The problem you appear to be running into is that your Smalltalk implementation considers Array an abstract class and therefore you need to instantiate a subclass of it to get a fixed size array.

blihp
  • 675
  • 4
  • 12
  • I am open to using a data structure different from an array. I'd appreciate it if you could update your answer to contain example code of how I could use a collection and how I'd add/remove elements to/from it. All of this being the instance variable within a class, of course. – Keagansed Sep 22 '18 at 15:31
  • Updated as you requested – blihp Sep 22 '18 at 16:18
  • Thank you very much. One last question before I accept it as the answer. What is the purpose of initialising it as 10 if it’s size is dynamic? – Keagansed Sep 22 '18 at 16:20
  • 1
    For many classes, sending #new: (as in new: 10) is an optional optimization when you know exactly or even roughly how many elements a collection will contain. I only used it in this case to minimize the changes I was making to your example. Generally, unless you have a very large collection (thousands of elements or more) I'd just stick with Orderedcollection new instead of OrderedCollection new: 10. – blihp Sep 22 '18 at 16:30
  • Ok, I’ll do that for what I need as well. Thank you very much. – Keagansed Sep 22 '18 at 16:31