Hi,
Robert said:
No, I'm not aware of this!? I would "implement" it to the Java-Spec
in a quite simple way: No method of a class that uses write-access to
a member can be marked as 'const'. When a variable is declared as
'const', only const-methods can be called.
But think of StringBuffer.toString(): the observable state of the
StringBuffer (i.e. the string) does not change but the internal state of
the instance changes to remember that the internal char[] is shared with a
String instance. You can't do that with your fairly simple definition.
Now, is toString() a const method or not?
Well, it is correct that I cant cover that with my definition.
I see some possibilities:
(1) Modify the class StringBuffer so that the array is not shared. To be
honest, I'm not sure if it is really necessary that the array is shared:
If the StringBuffer is modified after calling toString(), what happens?
I suppose, the char[] is copied, because the changes have to be only
visible to the StringBuffer, not to the String. The easiest solution is
to copy the char[] in the toString() method instead. (I guess what you
want to say now: calling toString() is usually done once in the
StringBuffers lifecycle, so in many cases, the copying is not really
necessary.)
(2) To avoid the unnecessary copy, it would be possible to introduce two
different String-Types: A mutable String and an immutable String. In
many cases, it is not really necessary that a String is immutable. So
why not make it mutable and mark it as 'const'? (I know that it's not
the same, but) It's sufficient in most cases.
Anyhow, the String/StringBuffer/StringBuilder-concept is not very clean
in java at the moment, IMHO. Especially the String-class is intended to
be a "Eierlegende Wollmilchsau" as we say in Germany - which means, it
is designed to be an absolutely universal class for any purpose, but in
reality because of this demand, its design is quite complex and (of
course) it does *not* cover every purpose (which is indeed impossible).
Why not clean it up completely?
(3) Introduce a new keyword to indicate that a member does not affect
the external state of an otherwise const object.
I must admit that the first solution is not the best one. The third
solution is perhaps not really complex, because I suppose, in most
cases, this would only be used for lazy initialisation. So, it would be
possible to restrict the keyword for that pattern.
The second solution however - the more I think about it - would be
necessary anyhow, not depending on our discussion around 'const', IMHO.
Why that? You just declared the List as const. Wouldn't this be better?
void foo(const List<const StringBuffer> l) {
l.get(0).append("bar"); // must cause a compiler-error
}
Interesting idea. But I think it doesnt work:
class StringBufferList extends List<StringBuffer> { ... }
void foo(const StringBufferList l) {
l.get(0).append("bar"); // must cause a compiler-error
}
How to indicate this to the compiler?
No, I think, the const-keyword has to be expanded automatically!
Probably not. For compiler developers the case might be different.
Using my original definition, it is not much more complex as final!
It seems you're not fully aware of how "const" and "mutable" work in C++.
That's correct.
In short, people noticed that it is desirable that the observable state of
an instance does not change (hence it should be const) but that the
internal state should be able to change in certain ways (=> caching, lazy
initialization). For that to work you use keyword "mutable" in C++, i.e.
you allow state changes on a const instance.
If you think a bit longer about this you may start to realize that "const"
is not simple alltogether. From my experience the question "what is
const" has not a trivial answer...
That's correct as well, it is not absolutely trivial. But I think it is
not sooo hard.
Not only difficulty but also volume can increase effort.
Well, I think, *both* were much higher when introducing generics.
I even go as far as I don't want to see it in the language.
Hmmm :-(
;-)
Ciao,
Ingo