Re: initializing classes

[email protected]
Newsgroups gmane.comp.audio.supercollider.user
Message-ID <[email protected]>
> Untill now I had one huge Class and all objects were functions, but this gets quite messy
You can use the "Component Pattern" to break a large monolith into
smaller components. Here's a good description:

https://gameprogrammingpatterns.com/component.html

The whole book is very recommended. As the title suggests, it focusses
on game programming, but the lesson can be applied to many other fields
of software development.


> Then I´m planing a hierarchy of those classes with subclasses
Generally, try to avoid deep convoluted class hierarchies (like those in
sclang :-). Often it is better and more maintable to use object
composition ("has-a") instead of inheritance ("is-a"), because it leads
to less coupling, keeps classes small and you don't run into the
"Diamond of Death" problem. If you absolutely need to use inheritance,
make sure to keep the class hierarchy as flat as possible.

In many statically typed languages, like C++ and Java, Inheritance is
necessary to achieve runtime polypmorphism. Typically, classes would
inherit from a common base classes with "empty" methods (= interface).

In dynamically typed languages, like Python, Javascript, sclang, etc.,
you can instead rely on "duck typing". There are much fewer actual use
cases for inheritance in dynamically typed languages than one would think.

Even in terms of code reuse, you can often decouple the common logic
from the domain specific logic. Subclassing is only really necessary if
(parts of) the additional logic has to be public, e. g. by exposing new
properties and methods. Otherwise, you can put all domain specific logic
into seperate classes and the main class just owns an instance of a
specific implementation.

Short example:

Widget {

     handleMousePress { ... }

     // many other event handlers

     draw { ... }

}

Now, a user might want to inherit from Widget to create a customized
version. At the same time, the Widget might have different ways of
drawing the content. The first instinct might be to write a subclass for
each and override the "draw" method, but this would mean that the user
would need to subclass each of those classes for their customized
version, leading to type explosion.

Instead, Widget should probably own (a reference to) a Renderer, so the
"draw" method could simply be:

draw { this.renderer.draw }

This is called "delegation".

There could be many different types of renderers (e.g. GDIRender,
CocoaRenderer, X11Renderer, GPURenderer, PDFRenderer, etc.), but this
fact is completely hidden from the user.

---

Finally, I would like to point out that you don't have to use sclang's
class system (= classic inheritance), you can also build your object
system with Events (= prototypical inheritance). Check out the
documentation of IdentityDictionary - especially the "parent" and
"proto" properties - for more information on this.

Hope this gives you some ideas.

Christof

Am 23.03.2021 um 12:15 schrieb [email protected]:
> Thanks for the two solutions!
>
> A follow-up question - I guess everybody does it a bit differently, but :
>
> I´d like to sort my object-templates in Classes - so Gliss would call a glissando Class, Cluster would call a cluster Class and so on.
> Then I´m planing a hierarchy of those classes with subclasses so the whole system is more manageable, but I’ll get quite a lot of different Classes.
>
> Is this a common / useful approach?
>
> Untill now I had one huge Class and all objects were functions, but this gets quite messy
>
>
>
>
>
>
>> Am 23.03.2021 um 00:15 schrieb [email protected]:
>>
>> On Tue, Mar 23, 2021 at 3:24 AM <[email protected]> wrote:
>>> This way it works, but then I have to initialize ALL variables, otherwise they are nil
>>>
>>> MyClass : MySuperClass{
>>> var <>midinote = #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
>>> var <>dur = 1;
>>> var <>legato=#[1, 0.1, 1];
>>>
>>> *new { |midinote, dur, legato|
>>> ^super.newCopyArgs(midinote,dur, legato)
>>> }
>>> }
>> Many classes do this by providing defaults to the *new arguments:
>>
>>     *new { |midinote = #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], dur =
>> 1, legato = #[1, 0.1, 1]|
>>         ^super.newCopyArgs(midinote,dur, legato)
>>     }
>>
>> hjh
>>
>> _______________________________________________
>> sc-users mailing list
>>
>> info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
>> archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
>> search: http://www.listarc.bham.ac.uk/lists/sc-users/search/
>
> _______________________________________________
> sc-users mailing list
>
> info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
> archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
> search: http://www.listarc.bham.ac.uk/lists/sc-users/search/

_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.