Abstract class
Aaron "Castironpi" Brady
castironpi at gmail.com
Sun Sep 14 15:21:54 EDT 2008
On Sep 14, 2:15 pm, Gary Herron <gher... at islandtraining.com> wrote:
> 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... at 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
: <MajorInterval '5th'>
note1 = SharpNote("G")
note2 = NaturalNote("C")
interval= note1- note2
print interval
: <MinorInterval '6th'>
WholeStep= MajorInterval( 2 )
print WholeStep
: <MajorInterval '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.NaturalNote( "E" ), octave.NaturalNote( "G" ),
octave.up.NaturalNote( "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
: <MinorInterval '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.defaultoctave )
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.defaultoctave
It's open to debate whether Natural is a subclass or instance of
Accidental.
More information about the Python-list
mailing list