I was trying to understand how you tie shared variables to encapsulation and 
what you meant by something that students later need to unlearn, and I think I 
understand now. You’re okay with shared mutable state as long as it’s clear 
that it’s not shared with the whole world but only with some explicit unit, and 
since an implicit class appears to be the whole world, then its fields seem to 
be globally shared, and that’s what you want to avoid your students learning. 
Is that correct?

Now, we’re not in the business of telling teachers how to teach, and I assume 
different teachers teach in different ways. Implicit classes are not 
exclusively a teaching construct, but a natural Java construct — a natural 
extension of implicit modules and packages. Expert programmers may also 
appreciate implicit classes just as they appreciate JShell and launching 
source-code programs, both of which are also explicitly motivated, at least in 
part, by education (see JEPs 222 and 330).

That natural Java construct *allows* teachers to teach in the order and style 
they choose without *forcing* classes on them. Some teachers may teach just 
basic control flow and (local) variables, perhaps records, and treat List, Map, 
and Set as built-in constructs without teaching any OOP in the first course and 
without teaching students how they can implement their own Lists etc. Some may 
choose to show shared variables (even if only to demonstrate their danger) 
while some may choose not to, although I assume everyone will teach constants. 
If you want to teach mutable fields only after introducing classes, that’s 
great and you can certainly do that (perhaps while enjoying the enhanced main 
and postponing static). But I don’t think the language should enforce a 
particular teaching style, where shared mutable state *must* be taught only in 
the context of classes. Even if you believe that doing otherwise is bad 
pedagogy, there is nothing that fundamentally ties shared variables to the 
ability to create class instances.

It’s true that we don’t want to cause harm by letting beginners learn something 
that needs to later be unlearned, but that’s not the case even for those who do 
learn about mutable fields. If students begin with implicit classes and seem to 
think that fields (if taught them) — or methods for that matter — are shared 
with the whole world, they invariably later learn that their “whole world” is 
actually a unit and that big programs are made by composing such units. They 
inevitably learn that because Java offers no other way. They *can’t* create a 
global variable, nor a global method, because Java simply doesn’t have those. 
Even if Java were to someday acquire package-level fields and methods (or even, 
hypothetically, module-level methods and fields), it still wouldn’t have a 
global namespace (not even for classes!). Learning that basic fact doesn’t 
require any unlearning, just contextualising.

So we're giving teachers more freedom than ever before to teach Java in the 
manner each of them chooses, and I don’t think we’re inflicting any harm in the 
process. I think that restricting the abilities of implicit classes further 
forces a particular teaching style — though some may consider it the only 
correct style — and would also be a less natural Java construct and a less 
enjoyable one for experienced programmers.

— Ron

On 18 Feb 2023, at 07:11, [email protected]<mailto:[email protected]> wrote:


yes.
from my experience, the time to introduce the notion of class is when you start 
to have shared mutable state. What i do not like with the implicit class 
proposal is the fact that you can have fields without defining the class around.
But i think there is a solution.

What about the feature being renamed to "implicit record" instead of "implicit 
class" ? We have no discuss why the container of an implicit "class" has to be 
a class instead of an annotation, an interface, an enum or a record.

Having the container to be an annotation is useless given that an annotation 
can not have a main.
If the container is an interface, methods are abstract by default which is not 
what we want.
If the container is an enum, then we are closer to the idea of Ron that it is a 
singleton, especially if the container defined one implicit enum member like 
"SINGLETON" . An enum can not be inherited and the default constructor is 
private which is are nice properties.
if the container is a record with no component, it can not be inherited, the 
constructor is package visible and more importantly to me, a user can not 
defined instance fields ...

I prefer implicit record to implicit class because with a record as container 
you can not introduce a shared mutable state by error, you have at least to 
write static in front of the field.

I dread about students being able to write code like this

  String name;

  void setName(String name) { this.name = name; }
  void hello() { System.out.println(name); }
  void main() {
    setName("Bob");
    ...
    hello();
  }

i.e to be able to declare mutable shared state without a class around (@Ron 
without class encapsulation).
At least if the container is a record, "name" in the example above has to be 
static, from the student POV, an unusual variable.

An implicit record has also the advantage that you do not have to introduce the 
notion of class to explain the notion of implicit container, given that records 
are far simpler at the beginning than class, having the implicit container 
being a record make sense because it's records all the way down.

What do you think about having the implicit container being a record instead of 
a class ?

Reply via email to