Submission: switch (...) instanceof feature

Tom Ball tball at google.com
Wed Apr 22 09:36:45 PDT 2009


In general I agree with your concern, but remember that those of us on this
alias have the ability to modify most of the code we use.  That's not true
in the Java community at large, where using existing code, such as
frameworks or libraries, is much more prevalent.  It's often not practical
to "write object.doSomething()" when working with external code, and that's
where this proposal helps.

Tom

On Tue, Apr 21, 2009 at 9:55 PM, Derek Foster <vapor1 at teleport.com> wrote:

> Like Gabriel, I have severe reservations about this proposal. I am
> concerned that it will encourage people to avoid the common OOP "best
> practice" of using virtual method dispatch in favor of doing an explicit
> "switch" on each subtype of a type, in cases where doing so is not
> necessary.
>
> I concede that there are a few (FEW!) places where doing the equivalent of
> a switch on instances of a type is necessary (for instance, if the type is
> in a library you don't have the ability to change). I can see some value in
> this proposal for that purpose. However, I would very much not like to see
> use of this construct become commonplace. I already see too many instances
> of people doing the equivalent of "if (object.type == FOO) {doThis(); } else
> if (object.type == BAR) { doThat(); }" instead of writing
> "object.doSomething();"
>
> Derek
>
> -----Original Message-----
> >From: Gabriel Belingueres <belingueres at gmail.com>
> >Sent: Mar 30, 2009 7:31 AM
> >To: Jeroen van Maanen <jeroen at entreact.com>
> >Cc: coin-dev at openjdk.java.net
> >Subject: Re: Submission: switch (...) instanceof feature
> >
> >IMO I'm against this.
> >
> >First, it is against current best practices for the design of
> >object-oriented software to make easier to code something with a case
> >statement on types/classes.
> >
> >Second:
> > void log(Object object) {
> >   switch (object) instanceof {
> >   case String:
> >     logger.debug("'" + object + "'");
> >   case Date:
> >     logger.debug(object.getTime());
> >   case void:
> >     logger.debug("null");
> >   default:
> >     logger.debug("<" + object.toString() + ">");
> >   }
> > }
> >
> >It think it is clearer (when possible) writing it with several
> >overloaded methods and double dispatching.
> >
> >Third:
> >   } catch (Exception exception) {
> >     switch (exception.getCause()) instanceof {
> >     case ParseException:
> >       log.warn("Could not get status for '" + id + ": " +
> >exception.getCause());
> >     default:
> >       log.warn("Could not get status for '" + id + ", exception);
> >     }
> >}
> >
> >in the case you intentionally left out the break statement, then the
> >switch statement is not any clearer than doing an if.
> >in the case that you wanted the break statement on the ParseException
> >case, it is even clearer to use two catch blocks (one for
> >ParseException and other for Throwable.
> >
> >
> >2009/3/29 Jeroen van Maanen <jeroen at entreact.com>:
> >> I'd like to coin a switch (...) instanceof statement as a new feature of
> the
> >> Java language. Please accept the attached proposal for review.
> >>
> >> Regards, Jeroen
> >>
> >> PROJECT COIN SMALL LANGUAGE CHANGE PROPOSAL FORM v1.0
> >>
> >> AUTHOR(S): Jeroen van Maanen <http://lexau.org/contact.html>
> >>
> >> OVERVIEW
> >>
> >> FEATURE SUMMARY: The instanceof switch statement allows for clear and
> >> concise
> >> handling of alternatives that depend on the type of a given object.
> >>
> >> MAJOR ADVANTAGE: The instanceof switch statement removes the need for
> >> different
> >> names for the same object with different types and the extra
> declarations
> >> and
> >> casts to define those names.
> >>
> >> MAJOR BENEFIT: Why is the platform better if the proposal is adopted?
> >>
> >> MAJOR DISADVANTAGE: Coders, reviewers, and IDE's need to be able to read
> the
> >> new statement and interpret and treat it correclty.
> >>
> >> ALTERNATIVES: There are no alternatives.
> >>
> >> EXAMPLES
> >>
> >> SIMPLE EXAMPLE:
> >>
> >>  void log(Object object) {
> >>    switch (object) instanceof {
> >>    case String:
> >>      logger.debug("'" + object + "'");
> >>    case Date:
> >>      logger.debug(object.getTime());
> >>    case void:
> >>      logger.debug("null");
> >>    default:
> >>      logger.debug("<" + object.toString() + ">");
> >>    }
> >>  }
> >>
> >> ADVANCED EXAMPLE:
> >>
> >>  public StatusEnum getStatus(String id) {
> >>    StatusEnum result;
> >>    try {
> >>      result = internalGetStatus(id);
> >>    } catch (Exception exception) {
> >>      switch (exception.getCause()) instanceof {
> >>      case ParseException:
> >>        log.warn("Could not get status for '" + id + ": " +
> >> exception.getCause());
> >>      default:
> >>        log.warn("Could not get status for '" + id + ", exception);
> >>      }
> >>    }
> >>  }
> >>
> >> public class PrettyPrinter {
> >>  private Writer writer;
> >>
> >>  public PrettyPrinter(Writer writer) {
> >>    this.writer = writer;
> >>  }
> >>
> >>  public write(Object object) {
> >>    switch (object) instanceof {
> >>      case String:
> >>        writer.write(stringDenotation(object));
> >>      case Collection:
> >>        writer.write(object.getClass().getSimpleName() + ": [");
> >>        for (Object element : object) {
> >>          write(element);
> >>          writer.write(",");
> >>        }
> >>        writer.write("]");
> >>      case Map:
> >>        write(object.entrySet());
> >>      case Map.Entry:
> >>        write(object.getKey());
> >>        writer.write(":");
> >>        write(object.getValue());
> >>      case void:
> >>        writer.write("null");
> >>      default:
> >>        // TODO: deal with arrays of unknown base type
> >>        writer.write("<" + object.toString() + ">");
> >>    }
> >>  }
> >>
> >>  private stringDenotation(String str) {
> >>    ...
> >>  }
> >>
> >> }
> >>
> >> DETAILS
> >>
> >> SPECIFICATION: The switch instanceof feature adds an alternative to the
> >> switch
> >> statement to the grammar.
> >>
> >>  SwitchStatement:
> >>    switch ( Expression ) SwitchBlock
> >>    switch ( Identifier ) instanceof TypeSwitchBlock
> >>
> >>  TypeSwitchBlock:
> >>    { TypeSwitchBlockStatementGroups? TypeSwitchLabels? }
> >>
> >>  TypeSwitchBlockStatementGroups:
> >>    TypeSwitchBlockStatementGroup
> >>    TypeSwitchBlockStatementGroups TypeSwitchBlockStatementGroup
> >>
> >>  TypeSwitchBlockStatementGroup:
> >>    TypeSwitchLabel BlockStatements
> >>
> >>  TypeSwitchLabel:
> >>    case Type :
> >>    case void :
> >>    default :
> >>
> >> COMPILATION: The statement
> >>
> >>  switch (<<identifier>>) instanceof {
> >>  case <<type1>>:
> >>    <<statements1 using identifier>>
> >>  case <<type2>>:
> >>    <<statements2>>
> >>  ...
> >>  case void:
> >>    <<statementsVoid>>
> >>  ...
> >>  default:
> >>    <<statementsDefault>>
> >>  }
> >>
> >> Would be compiled by desugaring it to
> >>
> >>  if (<<identifier>> instanceof <<type1>>) {
> >>    <<type1>> <<identifier + "$1">> = (<<type1>>) <<identifier>>;
> >>    <<statements1 with identifier replaced by identifier$1>>
> >>  }
> >>  else if (<<identifier>> instanceof <<type2>>) {
> >>    <<type2>> <<identifier + "$2">> = (<<type2>>) <<identifier>>;
> >>    <<statements2 with identifier replaced by identifier + "$2">>
> >>  }
> >>  ...
> >>  else if (<<identifier>> == null) {
> >>    <<statementsVoid>>
> >>  }
> >>  ...
> >>  else {
> >>    <<statementsDefault>>
> >>  }
> >>
> >> TESTING: The feature can be tested by compiling and running the examples
> and
> >> comparing the results with the had coded expected desugared versions.
> >>
> >> LIBRARY SUPPORT: The feature needs no additional library support.
> >>
> >> REFLECTIVE APIS: The feature does not affect reflective api's.
> >>
> >> OTHER CHANGES: The feature does not need other changes.
> >>
> >> MIGRATION: This feature does not invalidate existing code. An existing
> code
> >> base could be scanned for type casts. Occurrences of type casts should
> be
> >> manually evaluated and, if desired, recoded using the new feature.
> >>
> >> COMPATIBILITY
> >>
> >> BREAKING CHANGES: This feature does not invalidate existing code.
> >>
> >> EXISTING PROGRAMS: This feature has no impact on existing code.
> >>
> >> REFERENCES
> >>
> >> EXISTING BUGS: There are no existing Sun bug ids related to this
> proposal.
> >>
> >> URL FOR PROTOTYPE: Not available.
> >>
> >>
> >>
> >>
> >
>
>
>



More information about the coin-dev mailing list