So, I think you're bringing a mental model of "field" that might not be warranted.

In the context of an implicit class, all the members are effectively private, because the class is synthetic and therefore ordinary code can't call the constructor, access static members, use the class literal Foo.class, etc.  So the members of an unnamed class are accessible from the implicit class only, even if they are public (because the class name is a secret from everyone but the launcher.)

So to that end, you can start by teaching about statements:

    System.out.println("Foo!")

and that statements live in methods

    void main() {
        System.out.println("Foo!")
    }

and that methods can call methods:

    void greet() {
System.out.println("Foo!")
    }

    void main() {
        greet();
    }

and that methods can access variables:

    int greetCount = 0;

void greet() {
System.out.println("Foo!");
        ++greetCount;
    }

    void main() {
        greet();
        greet();
        System.out.println(STR."Now I've said it \{greetCount} times");
    }

From the perspective of a first-day student, the methods and variables are a sea of local members that can see each other.

Then, the curtain is pulled back, to reveal that these variables and methods are actually instance members on some instance of some class, which can be given a name and operated on from the outside.





On 2/20/2023 7:08 AM, [email protected] wrote:


------------------------------------------------------------------------

    *From: *"Ron Pressler" <[email protected]>
    *To: *"Remi Forax" <[email protected]>
    *Cc: *"Dan Heidinga" <[email protected]>, "Brian Goetz"
    <[email protected]>, "amber-spec-experts"
    <[email protected]>
    *Sent: *Monday, February 20, 2023 10:47:57 AM
    *Subject: *Re: Implicit Record Was: JEP draft: Implicit Classes
    and Enhanced Main Methods (Preview)

    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?


yes. But it's one of the arguments.

The real problem is dangling fields. Conceptually fields are far more "attached" to a class than methods (at least until you explain classes) but syntactically with an implicit class, you do not see that. Allowing dangling fields force the teacher to explain what an implicit class is which defeat the teaching purpose of it.


    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.


Agree, but there are some fundamentals, introducing fields without the notion of class is hard to envision.

    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).


yes,
Here we are discussing about ergonomics, i.e. is the "natural" extension is implicit class or implicit record ? With JEP 330, it's fear easier to create one file scripts written in Java instead of Python mostly because Python on Windows does not work as well as Python on Linux. I've seen several of those scripts on github, and there are not all using "class" as the top-level containers, some are using "interface", i've not seen a lot of scripts using records but record is a more novel construct. Implicit class is not necessary the right default.


    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.


Agree, i'm not suggesting that there is a right way to teach, i'm too old for that :) Before implicit class, introducing field declarations without classes is not something that was possible, so dangling fields is a new feature. As a teacher, the main reason to not allow dangling fields is that it creates confusion between local variables and fields which is a real issue students wrestle with.

Also, as a side remark, implicit class/record also creates new challenges from the teaching perspective, by example, you have to postpone explaining static quite a bit otherwise if you explain that main() can be a static method too soon, students will call you because this kind of code does not work

  static void main() {
    var color = new Color("blue");  // oops
  }

  class Color(String name) {
    ...
  }


My point is that while i agree that having an implicit container is a good idea, it does not make necessarily teaching easier, because an implicit container is a new feature that may interact badly with the rest of the features you want to teach.


    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.


Everything is encapsulated in Java, but dangling fields syntactically does not show that, that the issue.


    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.


The point is to teach Java, not to have to teach yet another new feature. Offering new freedom also implies introducing new complexity.


    — Ron


Rémi



        On 18 Feb 2023, at 07:11, [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