Can an EK9 record have no fields?

← Classes and OOP · Ref: Q2237

Only if it is abstract. A record exists only to carry data - it cannot have methods (E07290) - so a CONCRETE record with no fields, counting the ones it inherits, would hold nothing and do nothing: that is E07237. Two field-less shapes stay legal. An ABSTRACT record may have no fields: it is the root of a record hierarchy, the polymorphic type its sub-records share (Measurement below). And a sub-record may add no fields of its own when it INHERITS some (Altitude below inherits 'metres' from Length). For anything else, give the record the field it carries; if it was meant to carry behaviour, make it a class or component (a class or component with no fields is set simply by being present); if it was meant as a marker of one of a fixed set of values, use an enumeration. Every concrete record therefore has a field, which is also why every concrete record defines what 'set' means with its own '?' (E07235).

Example

defines module qa.records.need.fields

  defines record

    //A concrete record: it carries one field.
    Reading
      celsius <- 21.5
      default operator

    //The root of a record hierarchy may have no fields: it is abstract.
    Measurement as abstract
      operator $ as pure abstract
        <- rtn as String?
      default operator ?

    Length extends Measurement as open
      metres as Float: Float()

      Length() as pure
        -> distance as Float
        metres :=? distance

      default operator $
      default operator ?

    //Adds no field of its own, but inherits 'metres'.
    Altitude extends Length
      Altitude() as pure
        -> height as Float
        super(height)

      default operator $

  defines function

    describe()
      -> measurement as Measurement
      <- rtn as String: $measurement

  defines program

    RecordsNeedFields()
      stdout <- Stdout()
      reading <- Reading()
      stdout.println($reading)
      stdout.println(describe(Length(3.0)))
      stdout.println(describe(Altitude(8848.0)))

Common mistakes

E07237 — With its only field removed, the concrete record 'Reading' carries no data, and a record cannot have methods either, so it is pointless. Give it a field, make it a class or component if it carries behaviour, or mark it 'as abstract' if it is the root of a record hierarchy. See ek9 -h E07237 for details.

Incorrect:

    Reading

Correct:

    Reading
      celsius <- 21.5
Other ways to ask this
  • Why does EK9 reject an empty record?
  • Can I use an empty record as a marker type in EK9?
  • What does E07237 mean for a record?
  • Can an abstract record have no fields in EK9?

Coming from another language?

Java: an empty record 'record Marker() {}' compiles, and is used as a marker or tag. Kotlin: a data class needs at least one primary constructor parameter - the same rule as EK9, without EK9's abstract-root exception (Kotlin uses a sealed interface for that). Python: an empty @dataclass is legal. EK9 follows Kotlin: a record is data, so a concrete one must carry some; a polymorphic root is an abstract record (or a trait).

Keywords: abstract record, marker type, record, data class, empty record, record hierarchy, no fields, field-less