This is the mail archive of the kawa@sources.redhat.com mailing list for the Kawa project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: kawa-java string compatibility proposal


Based on the earlier posts in this thread, I believe "the other way"
refers to deriving a mutable class from an immutable one.

Not quite. I'm talking about deriving a mutable-string class from a general string class. The base class isn't "immutable". Rather, it lacks methods for mutation.

We have two types "immutable strings" and "mutable strings", and the
type of their union.  Java doesn't have union types, but we do need
a type for the union "strings".  We can use a class or interface for
this union, in which case we have three options:

(1)
abstract class string
class mutable_string extends string
final class immutable_string extends string
(string? x) == (instance? x <string>)
(mutable-string? x) == (instance? x <mutable_string>)
(imutable-string? x) == (instance? x <immutable_string>)

(2)
class string
class mutable_string extends string
(string? x) == (instance? x <string>)
(mutable-string? x) == (instance? x <mutable_string>)
(immutable-string? x) == (and (instance? x <string>)
                              (not (instance? <mutable_string>)))

(3)
class string
final class immutable_string extends string
(string? x) == (instance? x <string>)
(immutable-string? x) == (instance? x <immutable_string>)
(mutable-string? x) == (and (instance? x <string>)
                            (not (instance? <immutable_string>)))

A problem with (1) is how do you prevent people from deriving a
new class from string?  People are going to assume:
(string? x) == (or (immutable-string? x) (mutable-string? x))
That property *is* true for (2) and (3).

The problem with (3) is that it violates "widening":
  immutable_string x = new immutable_string("x");
  x.setCharAt(0, "z"); // run-time exception
  string y = x; // unsafe, but allowed
  y.setCharAt(0, "y"); // run-time exception
There are no compile-time complaints about this.  Instead we get
a ru-time error.  The general rule for widening conversions is that
they should not lose information and not risk a run-time exception.
Thus converting "int" to "long" or "String" to "Object" are both
considered "widening".  The inverse conversions are narrowings,
and require a casst, because they may lose information or throw
a run-time exception.  Converting an immutable_string to a string
*appears* to be a widening, acording to the Java hierarchy, but
it actually violates static typing.

Alternative (2) doesn't have this problem:
  mutable_string x = new mutable_string("x");
  x.setCharAt(0, "z"); // ok
  string y = x; // safe
  y.setCharAt(0, "y"); // compile-time error: no such method
  ((mutable_string) y).setCharAt(0, "y"); // Ok

Note that in (2) "new string(...)" does create an immutable value,
but string is not an immutable class.

If followed to their logical conclusion, "object-oriented design
principles" require immutable classes to be final.

Yes - you're basically talking about "value classes".


But only alternative (1) has an immutable class.

Note that in (2) "new string(...)" does create an immutable value,
but string is not an immutable class.
--
	--Per Bothner
per@bothner.com   http://per.bothner.com/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]