Search code examples
eiffel

Eiffel, multiple types conformance: a way to specify that a parameter is a descendent from A and B?


Is there a way (I'm sure there is out of runtime check...) to specify that a parameter or a variable in general conforms to multiple types? to avoid doing something such as

work (a_printer: PRINTER; a_scanner: SCANNER)
    do
      a_printer.print
      a_scanner.scan
        -- OR without second parameter
      if attached {SCANNER} a_printer as l_scanner then
         l_scanner.scan
      else
         throw RuntimeError
      end
    end

Solution

  • If feature work belongs to a class that may have formal generic parameters, it could be defined as taking one argument of the corresponding formal generic type:

    class X [D -> {PRINTER, SCANNER}] feature
        work (device: D)
            do
                device.scan
                device.print
            end
    end
    

    Then, at the caller site, one could make the call

    x.work (multi_function_device)
    

    where x has an appropriate type, e.g. X [MULTI_FUNCTION_PRINTER].

    If work could also be declared and implemented as a class feature, the temporary variable could be avoided:

    {X [like multi_function_device]}.work (multi_function_device)
    

    If the auxiliary class X is not an option, the current version of the language provides no means to declare an argument as conforming to more than 1 type (e.g., work (d: {PRINTER, SCANNER})), so you would have to resort to preconditions like

    work (p: PRINTER)
        require
            attached {SCANNER} p
        do
            check
                from_precondition: attached {SCANNER} p as s
            then
                s.scan
            end
            p.print
        end