E81066: a trait's 'operator close' is abstract (no body) - a trait holds no properties, so it has nothing to close; the class that holds the resource closes it in its own 'operator close'

Category: E81xxx-E83xxx Test configuration, execution and coverage · Reported in phase: EXPLICIT_TYPE_SYMBOL_DEFINITION · Classification: TRAIT_CLOSE_OPERATOR_NOT_ABSTRACT · All error codes

What went wrong

A trait declares an 'operator close' with a body. A trait's operator close is abstract: it has no body. A trait holds no properties, so it has nothing of its own to close, and a body there would run inside every class that has the trait. The class that holds a resource declares its own operator close and closes the resource there.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 1860 (Which of my types must declare their own operator close, and what may that close do?)
  • ek9 -q 1520 (When does EK9 close a closeable value, and where may I keep one?)

How to fix it

Remove the body from the trait's operator close, and write the close in the class that holds the resource. The [EXAMPLE] section below shows a trait whose close prints, then a 'Releasable' trait with a bodyless close and a 'Resource' class that overrides it with the work.

Common causes

  • Giving a trait a "default" close so that implementing classes need not write one.
  • Logging or tidying up in a trait's close; do it in the class's close.
  • A trait extending a closeable trait and overriding its close with a body.

See also

  • E81066: A trait's operator close must be abstract (this error)
  • E81067: A type with a closeable property must declare its own operator close
  • E81068: An open type's operator close calls an overridable method

Examples

Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.

Fails with E81066: a trait's 'operator close' is abstract (no body) - a trait holds no properties, so it has nothing to close; the class that holds the resource closes it in its own 'operator close'

#!ek9
defines module error.e81066.bad

  defines trait

    <?- VALID: a trait's operator close with no body is abstract -?>
    Releasable
      operator close as pure

    <?- VALID: the same, with 'abstract' written out -?>
    ExplicitlyReleasable
      operator close as pure abstract

    <?- BAD: a trait's operator close with a body -?>
    LoggingReleasable
      operator close as pure
        stdout <- Stdout()
        stdout.println("closing")

    <?- BAD: even a body that only checks something -?>
    CheckingReleasable
      operator close as pure
        require true

    <?- BAD: a trait extending a closeable trait and adding a close body -?>
    ExtendedReleasable with trait of Releasable
      override operator close as pure
        require true

  defines class

    <?- VALID: the class with the trait implements the close itself -?>
    Resource with trait of Releasable
      name as String?

      default private Resource()

      Resource()
        -> resourceName as String
        name: resourceName

      default operator ?

      override operator close as pure
        require name?

Fixed: Leave the trait's close abstract; the class that holds the resource closes it

#!ek9
defines module error.e81066.good

  defines trait

    Releasable
      operator close as pure

  defines class

    Resource with trait of Releasable
      name as String?

      default private Resource()

      Resource()
        -> resourceName as String
        name: resourceName

      default operator ?

      override operator close as pure
        stdout <- Stdout()
        stdout.println(`closing ${name}`)

Questions and answers

These Q&A entries show E81066 and its fix: