This file is indexed.

/usr/share/SuperCollider/HelpSource/Guides/WritingClasses.schelp is in supercollider-common 1:3.6.3~repack-5.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
title:: Writing Classes
summary:: Writing SuperCollider Classes
categories:: Language>OOP
related:: Reference/Classes

For a basic tutorial on how standard object-orientated classes are composed, look elsewhere
link::http://www.google.com/search?q=oop+class+tutorial::

note:: Class definitions are statically compiled when you launch supercollider or "recompile the library." This means
that class definitions must be saved into a file with the extension .sc, in a disk location where supercollider looks
for classes. Saving into the main class library (SCClassLibrary) is generally not recommended. It's preferable to use
either the user or system extension directories.

code::
Platform.userExtensionDir;   // Extensions available only to your user account
Platform.systemExtensionDir; // Extensions available to all users on the machine
::

It is not possible to enter a class definition into an interpreter window and execute it.
::



section:: Inheriting

code::
MyClass : SomeSuperclass {

}
::

Without specifying a superclass, link::Classes/Object:: is assumed as the default superclass.

code::
MyClass { // :Object is implied

}
::

section:: Methods

class methods are specified with the asterix within the class method, the keyword code::this:: refers to the class. A
class in SuperCollider is itself an object.  It is an instance of link::Classes/Class::. Instance methods are specified
within the instance method, the keyword code::this:: refers to the instance.

code::
MyClass {
    *classMethod { arg argument;

    }

    instanceMethod { arg argument;

    }
}
::


To return from the method use teletype::^:: (caret). Multiple exit points also possible. If no teletype::^:: is
specified, the method will return the instance (and in the case of Class methods, will return the class). There is no
such thing as returning void in SuperCollider.

code::
MyClass {
    someMethod {
        ^returnObject
    }

    someOtherMethod { arg aBoolean;
        if(aBoolean,{
            ^someObject
        },{
            ^someOtherObject
        })
    }

}
::


section:: New Instance creation

code::Object.new:: will return to you a new object. When overriding the class method code::.new:: you must call the
superclass, which in turn calls its superclass, up until code::Object.new:: is called and an object is actually created
and its memory allocated.

code::
MyClass {
    // this example adds no new functionality
    *new {
        ^super.new
    }

    // this is a normal constructor method
    *new1 { arg arga,argb,argc;
        ^super.new.init(arga,argb,argc)
    }
    init { arg arga,argb,argc;
        // do initiation here
    }
}
::

In this case note that code::super.new:: called the method new on the superclass and returned a new object. Subsequently
we are calling the code::.init:: method on that object, which is an instance method.

Warning:: If the superclass also happened to call super.new.init it will have expected to call the .init method defined
in that class (the superclass), but instead the message .init will find the implementation of the class that the object
actually is, which is our new subclass.  So you should use a unique method name like myclassinit if this is likely to be
a problem.
::

One easy way to copy the arguments passed to the instance variables when creating a class is to use newCopyArgs.  This
method will copy the arguments to the instance variables in the order that the variables were defined in the class,
starting the parent classes and working it's way down to the current class.

code::
MyClass {
    var <a,b,c;

    *new { arg a,b,c;
        ^super.newCopyArgs(a,b,c)
    }
}

MyChildClass : MyClass{
    var <d;

    *new { arg a,b,c,d;
        ^super.newCopyArgs(a,b,c,d)
    }
}
::

Over reliance on inheritance is usually a design flaw.  Explore "object composition" rather than trying to obtain all
your powers through inheritance. Is your "subclass" really some kind of "superclass" or are you just trying to swipe all
of daddy's methods? Do a websearch for Design Patterns.

Class variables are accessible within class methods and in any instance methods.

code::
MyClass {
    classvar myClassvar;
    var myInstanceVar;
}
::

For class initialization check code::initClass::.

section:: Overriding Methods (Overloading)

In order to change the behaviour of the superclass, often methods are overridden. Note that an object looks always for
the method it has defined first and then looks in the superclass. Here code::MyClass.value(2):: will return 6, not 4:

code::
Superclass {
    calculate { arg in; in * 2 }
    value { arg in; ^this.calculate(in) }
}

MyClass : Superclass {
    calculate { arg in; in * 3 }
}
::

If the method of the superclass is needed, it can be called by super.

code::
Superclass {
    var x;

    init {
        x = 5;
    }
}

MyClass : Superclass {
    var y;
    init {
        super.init;
        y = 6;
    }
}
::



section:: Getter Setter

SuperCollider demands that variables are not accessible outside of the class or instance. A method must be added to
explicitly give access:

code::
MyClass : Superclass {
    var myVariable;

    variable {
        ^myVariable
    }

    variable_ { arg newValue;
        myVariable = newValue;
    }
}
::

These are referred to as getter and setter methods. SuperCollider allows these methods to be easily added by adding teletype::<:: or
teletype::>::.

code::
MyClass {
    var <getMe, >setMe, <>getMeOrSetMe;
}
::

you now have the methods:

code::
someObject.getMe;
someObject.setMe_(value);
::

this also allows us to say:

code::
someObject.setMe = value;

someObject.getMeOrSetMe_(5);
someObject.getMeOrSetMe.postln;
::


A getter or setter method created in this fashion may be overridden in a subclass by manually writing the method setter
methods should take only one argument to support both ways of expression consistently.  eg.

code::
MyClass {
    variable_ { arg newValue;
        variable = newValue.clip(minval,maxval);
    }
}
::

A setter method should always return the receiver. This is standard OOP practice (outside of SuperCollider as well). Do
not return the new value from your setter.

code::
MyClass {
    variable_ { arg newValue;
        myVariable = newValue;
        ^newValue       // DO NOT DO THIS
    }
}
::

section:: External Method Files

Methods may be added to Classes in separate files.  This is equivalent to Protocols in Objective-C.  By convention, the
file name starts with a lower case letter: the name of the method or feature that the methods are supporting.

code::
+ Class {
    newMethod {
    }

    *newClassMethod {
    }
}
::


section:: Slotted classes

Classes defined with [slot] can use the syntax myClass[i] which will call myClass.at(i). This is usefull when defining
classes that inherit from a Collection type class.

code::
MyClass[slot] {
    *new {
         ^super.new
    }

    at {|i|
        ("Index "++i).postln
    }
}
::

code::
a = MyClass();
a[3];
::

Defining a custom array of Points:

code::
MyPointArray[slot] : RawArray {
    center { ^Point(*this.asArray.flop.collect{ |item| item.sum / item.size } ) }
    asArray{ ^this.collect{ |elem| elem.asArray } }
}
::


section:: Printing custom messages to post window

By default when postln is called on an class instance the name of the class is printed in a post window. When
code::postln:: or code::asString:: is called on a class instance, the class then calls code::printOn:: which can be
overridden to obtain more useful information.

code::
MyTestPoint {
    var <x, <y;

    *new{ |x,y| ^super.newCopyArgs(x,y) }

    printOn { arg stream;
        stream << "MyTestPoint( " << x << ", " << y << " )";
    }
}
::

code::
a = MyTestPoint(2,3);
::

subsection:: Defining custom asCompileString behaviour

A call to code::asCompileString:: should return a string which when evaluated creates the exact same instance of the
class. To define a custom behaviour one should either override code::storeOn:: or code::storeArgs::. The method
code::storeOn:: should return the string that evaluated creates the instance of the current object. The method
code::storeArgs:: should return an array with the arguments to be passed to code::TheClass.new::. In most cases this
method can be used instead of code::storeOn::.

code::
// either
MyTestPoint {
    var <x, <y;

    *new{ |x,y| ^super.newCopyArgs(x,y) }

    storeOn { arg stream;
        stream << "MyTestPoint.new(" << x << ", " << y << ")";
    }
}

// or
MyTestPoint {
    var <x, <y;

    *new{ |x,y| ^super.newCopyArgs(x,y) }

    storeArgs { arg stream;
        ^[x,y]
    }
}
::

code::
MyTestPoint(2,3).asCompileString;
::

section:: Catching methods that are not explicitly defined

It is possible to catch calls to methods that are not explicitly defined in a Class by overriding code::doesNotUnderstand::.

code::
MyClass {
    *new { ^super.new }

    doesNotUnderstand { arg selector...args;
        (this.class++" does not understand method "++selector);

        If(UGen.findRespondingMethodFor(selector).notNil){
            "But UGen understands this method".postln
        };
    }
}
::

code::
a = MyClass();
a.someMethodThatDoesNotExist
::

section:: Tricks and Traps

definitionList::

## "Superclass not found..."

|| In one given code file, you can only put classes that inherit from each Object, each other, and one external class.
In other words, you can't inherit from two separate classes that are defined in separate files.

If you should happen to declare a variable in a subclass and use the same name as a variable declared in a superclass,
you will find that both variables exist, but only the one in the object's actual class is accessible.  You should not do
that. This will at some point become an error worthy of compilation failure.
::