Music Theory: The Basics - a Ring I've recently started building an API that allows a consumer to create and manipulate musical entities such as notes, intervals, scales and chords.

The first step is to create a a foundation of base structures that are later used by the musical entities.
One such structure is a Ring. 

A ring in modular arithmic

A Ring is an integer's representation clamped between 0 and the ring size. Its Value is the integer it represents.  Its Size is the group size. Its Class is the congruent value clamped in the specified range. Its Group determines the number of ranges it's away from the reference group 0.

A ring from the perspective of Music Theory


  The way I'm using a ring is to define a musical note. A note consists
  of a pitch and a degree. The pitch is a number that represents the
  frequency of a note. A ring with size 12 is used to represent all
  semi-tones within a single octave. Each octave is a ring group.
  Another ring with size 7 is used to define the degree of the note.
  Common representations of degrees are {C, D, E, F, G, A, B} or
  do-re-mi-fa-sol-la-ti. The note C on the 5th octave is considered
  the reference note with pitch 0 and degree 0.


I want to be able to change a ring's properties.
The example below shows how the pitch of a note could be represented by a ring.

val pitch = Ring(0, 12)   // the pitch of note 'C5' 
pitch.Group = 1           // the pitch one octave higher 'C6'
pitch.Class = 2           // the pitch class changed to that of note 'D6'
println(pitch)            // Ring(Value=14, Size=12)


The example below shows how the degree of a note could be represented by a ring.

val degree = Ring(0, 7)   // the degree of note 'C5' 
degree.Group = 1          // the degree one octave higher 'C6'
degree.Class = 1          // the degree class changed to that of note 'D6'
println(degree)           // Ring(Value=8, Size=7)


This means the note D6 can be represented by pitch Ring(Value=14, Size=12) and degree Ring(Value=8, Size=7).

I have opted to use a mutable class and data class. 
I want a mutable class because I require a lot of manipulations to be chained. 
And I desire a data class because of its nature of hiding boiler-plate code and providing interesting methods such as copy.

val ring = someOtherRing.copy().setClass(2).setGroup(1)


I did read that data classes should be immutable.


  So my questions are:



Is it allowed to use the data class as mutable class?
Does it make sense that I combine mutable and data class for the Ring class?
Are there better alternatives to create an API class?


Any additional feedback on Kotlin guidelines, general guidelines, fluent-ish methods and varia is welcome as well.

Ring code:

import kotlin.math.*

data class Ring(var Value: Int, val Size: Int) {

    var Class: Int
        get() = modulo(Value)
        set(value) {
            Value = Group * Size + modulo(value)
        }

    var Group: Int
        get() = Value / Size
        set(value) {
            Value = value * Size + Class
        }

    fun setValue(value: Int): Ring {
        Value = value
        return this
    }

    fun setClass(clazz: Int): Ring {
        Class = clazz
        return this
    }

    fun setGroup(group: Int): Ring {
        Group = group
        return this
    }

    private fun modulo(x: Int): Int {
        return (x % Size + Size) % Size
    }
}
Your concepts look completely misguided.

A ring is a mathematical concept, an algebraic structure. It does have a size, but it doesn't have a value.

The value would be part of a ring element. Such a ring element is a tuple (ring, value).

The pitch of a note is indeed a ring element. A ring element can only be used to store the pitch of a note, but not its octave. If it did, it would not match the mathematical concept of a ring anymore.

To represent a musical note in Western notation, my first idea is:

data class Note(
    val octave: Int,
    val name: NoteName,
    val mod: NoteModifier,
    val duration: NoteDuration
)

enum class NoteName {
    C, D, E, F, G, A, B
}

enum class NoteModifier {
    Natural, Sharp, Flat, TwoSharp, TwoFlat
}

enum class NoteDuration {
    Full, Half, Quarter, Eighth, Sixteenth
}


The above definitions are very rough and limited. To get a grasp of the actual complexity of typesetting music, have a look at LilyPond, it should have a definition of a note somewhere in the code.

If you just want to replay the music, there's no need to distinguish between c# and d\$\flat\$, which would make the above definitions much simpler.

In Kotlin you don't need setters since the copy function is more powerful than in Java. You can just say:

val note = other.copy(octave = 3, pitch = 5)


This is easier to grasp and less code to write. If you write a setter method in Kotlin, lean back and think twice. Probably you are doing something unusual.

By the way, property names in Kotlin are written in lowercase. Kotlin is based on Java, not C#.