On Sep 14, 2:15*pm, Gary Herron <gher...@island training.comwro te:
Mr.SpOOn wrote:
Gary Harron:
I believe you are mixing up class *inheritance* and *abstract* classes..
Class inheritance (with Python has has for years) is how one class inherits >behavior/properties/attributes from another class. *The class being inherited from is >called the base class. *This is probably what you want.
Well, I know the difference between an abstract class and an inherited
one. The idea was to create a main class Note, with abstract methods,
and implement these methods in the other classes.
On Sun, Sep 14, 2008 at 7:56 PM, Roy Smith <r...@panix.com wrote:
What properties or behaviors does SharpNote have which NaturalNote doesn't?
Unless there is some new behavior, you don't need subclasses.
Well, from a SharpNote I can obtain the relative NaturalNote. So if I
have a C# I can call
natural('C#') *and get 'C'
While in the class NaturalNote I don't need such a method, but I need
two methods to get the sharped and flatted version
Are you also going to have DoubleSharpNote and DoubleFlatNote?
Yes, that's an option.
Consider the following code:
note1 = SharpNote("E4")
note2 = NaturalNote("F4 ")
if note1 == note2:
* print "the same note"
else
* print "different notes"
what should it print?
Well, that's not so simple. The idea is that I use a notation (A, B,
C, D...) and an integer (a distance expressed in semitones) to
identify a note.
Anyway, I think I need an abstract class. Or not?
No! *Definitely not! * *You need inheritance of a class from a base
class. *
Just brainstorming with you. You can support operations on the
objects: note minus note = interval, note plus interval = note, and so
on. (WARNING! Spoilers. Untested.)
note1 = NaturalNote("G" )
note2 = NaturalNote("C" )
interval= note1- note2
print interval
: <MajorInterva l '5th'>
note1 = SharpNote("G")
note2 = NaturalNote("C" )
interval= note1- note2
print interval
: <MinorInterva l '6th'>
WholeStep= MajorInterval( 2 )
print WholeStep
: <MajorInterva l '2nd'>
note1 = NaturalNote("C" )
print note1- WholeStep
: <FlatNote("B" )>
However, from what I understand (brass player), there are some cases
in which you'll want that to be:
print note1- WholeStep
: <SharpNote("A") >
What do you want to determine that? What about a KeyOf class?
key= KeyOf( NaturalNote( "F" ) )
#'key' has special subclasses
note1 = key.NaturalNote ("C")
print note1- WholeStep
: <FlatNote("B" )>
key= KeyOf( SharpNote( "G" ) )
note1 = key.NaturalNote ("C")
print note1- WholeStep
: <SharpNote("A") >
Further, perhaps you want a 'WrittenNote' class which refers to the
key signature it's written in:
key= KeyOf( NaturalNote( "F" ) )
note1 = key.WrittenNote ("B")
print note1
: <FlatNote("B" )>
I do not immediately see how to represent clefs and staves: whether
you'll need them at all, or whether they're just writing/rendering
techniques.
As for scales and chords, are there any special methods you want on
them, or would a tuple of Note instances suffice?
triad= ( NaturalNote( "C" ), NaturalNote( "E" ), NaturalNote( "G" ) )
One special method might be:
triad= Triad( NaturalNote( "C" ), NaturalNote( "E" ),
NaturalNote( "G" ) )
print triad
: <C-Major triad>
triad= Triad( NaturalNote( "E" ), NaturalNote( "G" ),
NaturalNote( "C" ) )
print triad
: <C-Major triad 1st inversion>
I forgot about octaves, which can complicate the constructors.
octave= Octave( 4 ) #middle C
triad= Triad( octave.NaturalN ote( "E" ), octave.NaturalN ote( "G" ),
octave.up.Natur alNote( "C" ) )
print triad
: <C-Major triad 1st inversion>
Or:
octave= Octave( 4 )
triad= Triad( NaturalNote( "E", octave ), NaturalNote( "G", octave ),
NaturalNote( "C", octave.up ) )
print triad
: <C-Major triad 1st inversion>
And abbreviate the name for the interval.
octaveint= MajorInterval( 8 )
Abstract scales can be a tuple of intervals, where concrete scales are
a tuple of notes.
majorscale= ( Tonic, WholeStep, WholeStep, HalfStep,
WholeStep, WholeStep, WholeStep, HalfStep )
majorCscale= [ NaturalNote( "C" )+ x for x in majorscale ]
majorDscale= [ NaturalNote( "D" )+ x for x in majorscale ]
To get a little more creative, you could just denote sharps and flats
with a parameter:
note1 = Note("G", sharp)
#Or: note1 = Note("G", Note.sharp)
note2 = Note("C")
interval= note1- note2
print interval
: <MinorInterva l '6th'>
It would just take some 'parameter magic' to interpret them right when
paired with octaves:
octave= Octave( 4 ) #middle C
note1= Note( "C", sharp, octave )
note2= Note( "C", octave )
note3= Note( "C", octave, sharp )
note4= Note( "C", sharp )
That part just takes a little untwisting. (Untested.)
class Note:
defaultoctave= 4
def __init__( self, *args ):
octave= Octave( self.defaultoct ave )
accidental= Natural( )
for arg in args:
if issubclass( arg, Accidental ):
accidental= arg
elif issubclass( arg, Octave ):
octave= arg
elif type( arg ) is str:
name= arg
Or use keywords to specify.
octave= Octave( 4 ) #middle C
note1= Note( "C", sharp, octave )
note2= Note( "C", octave= octave )
note3= Note( "C", octave= octave, accidental= sharp )
note4= Note( "C", sharp )
class Note:
defaultoctave= 4
def __init__( self, name, octave= None, accidental= Natural( ) ):
if octave is None:
octave= self.defaultoct ave
It's open to debate whether Natural is a subclass or instance of
Accidental.