Forums before death by AOL, social media and spammers... "We can't have nice things"
|    comp.lang.pascal.borland    |    Borland Pascal was actually pretty neat    |    2,978 messages    |
[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]
|    Message 2,616 of 2,978    |
|    Femme Verbeek to Jim Leonard    |
|    Re: How to handle this OOP/inheritance p    |
|    05 Feb 08 22:01:32    |
   
   b017d411   
   From: fv2006@nospam.tcenl.com   
      
   Jim Leonard schreef:   
   > For a hobbyist project, I'm writing a music composer, and I really   
   > want to make it object-oriented because the data really lends itself   
   > to OOP for reasons I'll explain later. The only problem is that,   
   > while I'm a competent Pascal programmer, I've never done OOP before.   
   > My environment is Turbo Pascal 7.0. Before I lay out the details, I   
   > want to stress this is not a homework assignment :-) I am not asking   
   > for code, just the normal, best-practices way to do what I want to   
   > accomplish.   
   >   
   > I thought of creating a "song" object with the ability to enter notes,   
   > save/load the song data, etc because it makes perfect sense; the   
   > methods can validate the data and generally abstract the song. But   
   > the song needs to play, and that's where I get stuck on the proper way   
   > to program in OOP to access the song data. Should I:   
   >   
   > - Make a new "player" object that inherits the song object (so that it   
   > can directly reference the song data structures)?   
   > - Make a new "player" object that calls the song object's methods to   
   > pass the data back and forth?   
   > - Have the song object pass a pointer to the note data to be accessed   
   > by the player object? (that seems like it's defeating the whole   
   > purpose of OOP)   
   > - Build the playback routines directly into the song object, so that I   
   > have a single object with a gazillion methods?   
   >   
   > The program needs to be able to play the song, not only for one   
   > particular output device, but several. That means the playback   
   > routines need to be VIRTUAL so that I can replace them with methods   
   > for additional sound devices as I code them. It is that requirement   
   > that has me confused about the proper direction to take.   
   >   
   > I was leaning toward this:   
   > A song object;   
   > a player object that inherits the song object and contains only   
   > generic VIRTUAL playback methods;   
   > a device-specific object that replaces the virtual methods with   
   > methods for that device's hardware.   
   > I figure that way I can get direct access to the song's data   
   > structures without "exposing them to the outside", and I can keep   
   > building on previous code as necessary.   
   >   
   > Does that sound like the right way to go, or am I barking up the wrong   
   > tree?   
      
   Interesting project. Controlling the PC sound possibilities in TP or BP   
   is not easy. In don't know how you would organise this. Perhaps Delphi   
   will give you more possibilities here. But you are very right that this   
   kind of program requires OOP.   
      
   If you can get your hands on a copy of Borland Pascal with objects V7.01   
   I would strongly recommend this instead of TP7. Try to find a legal   
   copy, but for educational projects no one will care if you try to find   
   the BP.Zip installation file somewhere   
      
   Inheritance is very handy if there are several enteties that all need to   
   be treated more or less in the same way.   
      
   E.g. A note and a tone have the parameter "duration" in common, but a   
   note has the added parameters heigth, volume, rampup and rampdown etc.   
   So it is logical that TNote is a descendant of TTone, which in itself   
   descends from Tobject. Both will have a play method that can be used,   
   but TTone will override the Play method of TNote.   
      
   Next is to define the Melody object, which can best be a descendant of   
   Tcollection. The collection can be filled with objects either being note   
   or tone.   
      
   The common factor between violin, piano and drum is that they are all   
   different kinds of musical instruments. So if you want to load them in a   
   player there should be an inherited common method e.g. Play.   
      
   type   
   PInstrument:^TInstrument;   
   TInstrument:object(tobject)   
    melody:tmelody;   
    constructor init:   
    destructor done;   
    procedure play; virtual;   
   end;   
      
      
   implementation   
      
   constructor TInstrument.init;   
   begin   
    melody.init;   
   end;   
      
   Procedure TInstrument.play;   
   begin   
    abstract; {Always to be overridden by a descendant}   
   end;   
      
   destructor TInstrument.done   
   begin   
    melody.done;   
   end;   
      
      
   The abstract statement will generate an error on execution. This   
   procedure should always be overwritten by the actual instruments of   
   piano, violin and drum which are descendants of TInstrument. Each of   
   them holds different sound samples and different ways on how to connect   
   the tone and duration to the sound sample.   
      
   The player will probably have a list of instruments that can all play   
   simulataneously. In order to call a method of an instrument of unknown   
   implementation, you can simply call the abstract method of the parent.   
      
   Something like   
      
   Procedure tplayer.play   
    procedure plee(p:pinstrument);far;   
    begin   
    p^.play;   
    end;   
   begin   
    foreach(@plee);   
   end:   
      
      
   But the puzzle is entirely yours. There are more ways to do what you want.   
      
   Good luck   
      
   -- Femme   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|
[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]
(c) 1994, bbs@darkrealms.ca