Logo etsi

ETSI's Bug Tracker

Notice: information submitted on the ETSI issue Tracker may be incorporated in ETSI publication(s) and therefore subject to the ETSI IPR policy.

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0007862Ext Pack: Object-oriented features (ES 203 790)[All Projects] Generalpublic26-08-2019 12:5828-12-2020 13:04
ReporterJacob Wieland - Spirent 
Assigned ToJens Grabowski 
PrioritynormalSeverityminorReproducibilityhave not tried
StatusclosedResolutionfixed 
PlatformOSOS Version
Product VersionV1.2.1 (published 2020-05) 
Target VersionV1.3.1 (ongoing)Fixed in Version 
Summary0007862: Allow trait classes and multiple inheritance
DescriptionA trait class is a form of abstract class that can not be created but only extended. It can only extend other trait classes.

A normal class should be allowed to extend a list of trait classes beside its superclass. It inherits all members from all the trait classes it extends.

If a class extends two classes which both provide a member with the same name, that member shall be inherited from the same *defining* class (the most concrete extended class defining or overriding that member). If a trait and a class both need to access the same field, that field shall be inherited from the same defining trait class.

Fields of trait classes shall not have an initializer. Trait classes also do not have a constructor.

Example:

external function newGlobalId() return charstring;

type class @trait Identifiable {
  private var charstring id;
  public function setId(charstring id) {
    this.id := id;
  }

  public function getId() return charstring {
    return id;
  }
}

type class MyIdentifiableClass extends Identifiable {
  create(charstring id) {
    setId(id);
  }
}

var Identifiable v_idObj := MyIdentifiableClass.create("1");
var charstring v_id := v_idObj.getId();

Example 2: parallel inheritance

type class @trait A {
  function @abstract f();
}

type class @trait B {
  function @abstract f();
}

type class C extends A, B {
  // illegal, as it inherits A.f() and B.f()
}

type class @trait B2 extends A {}

type class C2 extends A, B2 { // legal, as it inherits only A.f()
  function f() { ... }
}

type class C3 extends A {
  function f() { ... }
}

type class D extends C2, C3 {
  // illegal, as it inherits C2.f() and C3.f()
}
TagsNo tags attached.
Attached Filesdocx file icon CR7862.docx [^] (146,209 bytes) 28-08-2019 12:10
docx file icon CR7862-2.docx [^] (167,362 bytes) 28-08-2019 13:51
docx file icon CR7862-3.docx [^] (148,469 bytes) 28-08-2019 14:17
docx file icon CR7862-4.docx [^] (148,365 bytes) 07-10-2020 12:26
docx file icon CR7862-5.docx [^] (148,418 bytes) 07-12-2020 13:18
docx file icon CR7862-6.docx [^] (149,147 bytes) 09-12-2020 19:11

- Relationships

-  Notes
(0015466)
Kristóf Szabados (reporter)
27-08-2019 09:41

so multiple extension is only allowed for extending trait classes, and this extension behaves as a copy-paste of the trait's content, right?
(0015469)
Jacob Wieland - Spirent (reporter)
27-08-2019 11:59

I would consider it more as a sort of flattening where first you flatten the definition of each extended class (keeping track of the original class of each member) and then merge the resulting class bodies of the flattened classes into one effective superclass while removing duplicates that come from the same (non-flattened) class body.

type class @trait A {
  var integer a;
}

type class @trait B {
  var integer b;
}

type class @trait C {
  var integer c;
}

type class @trait D extends B, C {
}

==> D is the same (ignoring subtyping) as:

type class @trait D {
  var integer a; // a is inherited via B and C, but only added once!
  var integer b;
  var integer c;
}
(0015470)
Jacob Wieland - Spirent (reporter)
27-08-2019 12:03

flattened B:

type class @trait B {
  var integer a; [from A]
  var integer b; [from B]
}

flattened C:

type class @trait C {
  var integer a; [from A]
  var integer c; [from C]
}

If we now add a class C2:

type class @trait C2 {
  var integer c;
}

then

type class @trait D2 extends C, C2 {
}

would result in a flattened class:

type class @trait D2 {
  var integer a; [from A]
  var integer c; [from C]
  var integer c; [from C2]
}

which is illegal (it has c from C and C2)
(0015477)
Jacob Wieland - Spirent (reporter)
27-08-2019 14:50

STF discussions: maybe not allow fields in trait classes
(0015482)
Jacob Wieland - Spirent (reporter)
28-08-2019 12:20

I have uploaded a proposal.

I have kept the possibility of fields (as the same problem already occurs with components and the same solution can be used).

I also relaxed the parallel inheritance restriction somewhat insofar that if you inherit from one class A function A.f() and from another class you inherit B.f() which overrides A.f() (directly or indirectly) through extension, then this shall also be allowed.

Consider the following rather typical scenario.

type class @trait HasX {
  function @abstract getX() return integer;
}

type class @abstract A extends HasX {
  // implementation using getX()
}

type class @trait HasXImpl {
  var integer x;
  function getX() return integer {
    return x;
  }
}

type class AImpl extends A, HasXImpl {
  // inherits only HasXImpl.getX() because it overrides HasX.getX()
  create(integer x) {
    this.x := x;
  }
}

So, one version of an implementation can only 'win' over another if there is a clear overriding relationship between them (which can be established via topological sorting).
(0015484)
Kristóf Szabados (reporter)
28-08-2019 12:29

Shouldn't HasXImpl extend HasX for this to work?
Now they are just 2 classes that happen to have functions with the same name.
(0015485)
Jacob Wieland - Spirent (reporter)
28-08-2019 12:37

Please review
(0015487)
Kristóf Szabados (reporter)
28-08-2019 13:32

The wording is a bit strange now.
in 5.1.1.0 the new J restriction sounds like saying no 2 (even unrelated) classes can have fields with the same name (the same extending class would have to extend both classes for this to be problem, even then it would not be a problem with the fields, but the extension).

restriction k sounds like implying a direct extension tree.

restriction m is saying that each class can be extended only once (which not be very useful)
(0015488)
Tomas Urban (developer)
28-08-2019 13:53

I made changes to the revisions j, k and m. Please review.
(0015489)
Kristóf Szabados (reporter)
28-08-2019 14:20

Added a note on the not so obvious way of making a backward incompatible change, please check.

The rest of the text is fine, but maybe we should sleep on it to see if we can come up with a wording, that is not suggesting multiple inheritance support this much.
(0015490)
Tomas Urban (developer)
28-08-2019 14:40

The note added by Kristof is fine. The proposal can be added to the specification, but since Kristof suggests postponing, I won't mark it as resolved yet.
(0015565)
Kristóf Szabados (reporter)
18-12-2019 07:41

To me the current text still sounds very much like a normal multiple inheritance feature, which we aggreed to not have as a general guideline in the beginning.

Ok it is cumbersome for a multiple-inheritance, since one has to write his own initializer functions, and create some "dummy" class on the top of the hierarchy to be able to instantiate it ... yet it still is multiple-inheritance.

Or I might miss some part that forbids this kind of understanding and emphasizes flattening.
(0015578)
Jacob Wieland - Spirent (reporter)
18-12-2019 11:10

Yes, it is multiple inheritence but much more restrictive than C++ multiple inheritance, avoiding diamond problems and clashing definitions.

Also, the general guidelines in the beginning were (as far as I remember) meant for the first version of the OO feature where we explicitly kept the possibility of multiple inheritance open, so I don't understand why this is relevant for this additional OO feature.
(0015580)
Jens Grabowski (manager)
18-12-2019 11:35

STF discussion: It was agreed that some sort of multiple inheritance should be supported. The concrete implementation, e.g., interfaces or trait classes or something else, need to be discussed in 2020.
(0015761)
Jens Grabowski (manager)
06-10-2020 13:54

STF decision: Only JAVA-like interfaces without defaults.
(0015774)
Jacob Wieland - Spirent (reporter)
07-10-2020 12:27

updated with the agreed-on restrictions, please review
(0015780)
Kristóf Szabados (reporter)
08-10-2020 13:28

Some notes:
1)
"adding a new overriding function to an existing normal or trait class is semantically valid in its own context"
What is the purpose of a trait class overriding a function of an other trait class?
As neither can have bodies, this sounds questionable.

2)
Other than the previous question why would it be non-backward compatible if a normal class extends two independend trait classes, that are added new overriding functions?
As these functions can not have bodies, and have the same signature, if this repetition/oberriding is allowed, it just repeats that the extending normal classes have to have a function with that signature.

3)
"type class C2 extends A, B2 { // legal, as it inherits only B2.f()"
and
"type class E extends A, C2 {
  // legal, it does not inherit A.f() as this is overriden by C2.f()
"
It is actually not trivial. While I could agree it is not trivial why inheriting via 2 different inheritance trees of trait classes is allowed. As far as I understand the reason, is that both inheritance trees in the end define that there must be a function with that signature in the extending normal class, and none of the functions in the trait classes has bodies. As such it might be better to say, that it is legal since both traits being extended require the presence of a function with the exact same signature and there is no normal class extended.
(0015784)
Jacob Wieland - Spirent (reporter)
08-10-2020 15:50

1) is for future expansion of the trait concept, if both traits add the same function, this shall be a clash, so one needs to override the other.

But, of course, we could remove that restriction for now, would also need to be done in the example.

I don't understand question 2.

3) is in essence also to avoid confusion, if you inherit two functions of the same name from different sources, you would have to check whether they have the same parameters. With this, you can only inherit it from one source, so the question of comparison side-by-side inherited things becomes moot.

Again, we can also remove this, it will have to be re-added once we allow trait-members with bodies, though.
(0015785)
Jacob Wieland - Spirent (reporter)
08-10-2020 15:55

Adding functions to traits is potentially non-backward compatible as it cannot be assured that all classes inheriting the trait directly or indirectly already implement that new function. Even if you implement it in all classes that are under your control, some other source can have used a class implementing the former version of the trait and not implement the new function. Thereby, you are potentially breaking the using code.

Same is true for adding any members in any class (even private), as you can never know if a subclass already has a member of that name and thus would be broken by your change. This is normal, except for private members.
(0015797)
Jacob Wieland - Spirent (reporter)
07-12-2020 13:20

I have removed the trait-related restrictions not necessary for only-interface-traits and changed the examples accordingly. Please review.
(0015819)
Tomas Urban (developer)
09-12-2020 08:02

It looks fine by me. It is quite restrictive at moment, but it is possible to add more complicated features (like non-abstract functions on the trait level) in the future.

I have only two technical comments:
1. Since the restrictions j and k were added in this proposal, I would not mark them as "Void", but remove completely so that we won't accidentally add them to the standard.
2. The note for the restriction k should be moved to the semantic rules.

Kristof, you revised the previous versions of the proposed changes. Could you please check this one as well?
(0015828)
Kristóf Szabados (reporter)
09-12-2020 19:16

For the first point I have removed restriction j and k (that were changed to void.

For the second point I have just removed the note as the situation described in it is not possible.
The note said: ... "if they also extend an other (possibly independent) trait that also overrides the same function but with different formal parameters or return clause"

This is not possible as section 5.1.1.7 declares:
- "A method inherited from a superclass can be overridden by the subclass by redefining a function of the same name and with the same formal parameter list."
- "The return type of an overriding function shall be the same as the return type of the overridden function with the same template restrictions and modifiers"
(0015829)
Kristóf Szabados (reporter)
09-12-2020 19:17

Please check the new version.
(0015832)
Tomas Urban (developer)
10-12-2020 07:33

Well, I think that what Jacob meant is that developers have to be careful when adding new methods to classes and traits if these are extended in other projects that are not under their control. You are right that it would produce an error. However, it is true only if the developer can compile the whole code and that's not always the case.

The question is if we need this kind of note or not. From my point of view, it is not necessary because (as Kristof pointed out) there are clear rules for parameters and return values of methods whose name is present on a superclass or supertrait level. Jacob, could you please comment the note issue? If you don't insist on having it, I think it is possible to resolve the CR.
(0015839)
Jens Grabowski (manager)
10-12-2020 09:21

STF discussion: Note should be added in a more prominent place. This CR is resolved with version 6 of the resolution.

- Issue History
Date Modified Username Field Change
26-08-2019 12:58 Jacob Wieland - Spirent New Issue
26-08-2019 12:58 Jacob Wieland - Spirent Status new => assigned
26-08-2019 12:58 Jacob Wieland - Spirent Assigned To => Jacob Wieland - Spirent
26-08-2019 14:28 Jacob Wieland - Spirent Status assigned => new
27-08-2019 09:41 Kristóf Szabados Note Added: 0015466
27-08-2019 11:59 Jacob Wieland - Spirent Note Added: 0015469
27-08-2019 12:03 Jacob Wieland - Spirent Note Added: 0015470
27-08-2019 14:50 Jacob Wieland - Spirent Note Added: 0015477
27-08-2019 14:50 Jacob Wieland - Spirent Status new => assigned
28-08-2019 12:10 Jacob Wieland - Spirent File Added: CR7862.docx
28-08-2019 12:20 Jacob Wieland - Spirent Note Added: 0015482
28-08-2019 12:29 Kristóf Szabados Note Added: 0015484
28-08-2019 12:37 Jacob Wieland - Spirent Note Added: 0015485
28-08-2019 12:37 Jacob Wieland - Spirent Assigned To Jacob Wieland - Spirent => Tomas Urban
28-08-2019 12:37 Jacob Wieland - Spirent Status assigned => confirmed
28-08-2019 13:32 Kristóf Szabados Note Added: 0015487
28-08-2019 13:51 Tomas Urban File Added: CR7862-2.docx
28-08-2019 13:53 Tomas Urban Note Added: 0015488
28-08-2019 13:53 Tomas Urban Assigned To Tomas Urban => Kristof.Szabados
28-08-2019 14:17 Kristóf Szabados File Added: CR7862-3.docx
28-08-2019 14:20 Kristóf Szabados Note Added: 0015489
28-08-2019 14:20 Kristóf Szabados Assigned To Kristof.Szabados => Tomas Urban
28-08-2019 14:20 Kristóf Szabados Status confirmed => assigned
28-08-2019 14:21 Kristóf Szabados Status assigned => confirmed
28-08-2019 14:40 Tomas Urban Note Added: 0015490
28-08-2019 14:40 Tomas Urban Assigned To Tomas Urban => Jens Grabowski
17-12-2019 11:22 Jens Grabowski Assigned To Jens Grabowski => Kristóf Szabados
17-12-2019 11:22 Jens Grabowski Status confirmed => assigned
18-12-2019 07:41 Kristóf Szabados Note Added: 0015565
18-12-2019 11:10 Jacob Wieland - Spirent Note Added: 0015578
18-12-2019 11:35 Jens Grabowski Note Added: 0015580
18-12-2019 11:35 Jens Grabowski Assigned To Kristóf Szabados => Jens Grabowski
14-08-2020 11:26 Jens Grabowski Assigned To Jens Grabowski => Kristóf Szabados
06-10-2020 13:53 Jens Grabowski Assigned To Kristóf Szabados => Jacob Wieland - Spirent
06-10-2020 13:54 Jens Grabowski Note Added: 0015761
07-10-2020 12:26 Jacob Wieland - Spirent File Added: CR7862-4.docx
07-10-2020 12:27 Jacob Wieland - Spirent Note Added: 0015774
07-10-2020 12:27 Jacob Wieland - Spirent Assigned To Jacob Wieland - Spirent => Kristof.Szabados
07-10-2020 12:27 Jacob Wieland - Spirent Status assigned => confirmed
08-10-2020 13:28 Kristóf Szabados Note Added: 0015780
08-10-2020 13:29 Kristóf Szabados Assigned To Kristof.Szabados => Jacob Wieland - Spirent
08-10-2020 13:29 Kristóf Szabados Status confirmed => assigned
08-10-2020 13:29 Kristóf Szabados Status assigned => confirmed
08-10-2020 15:50 Jacob Wieland - Spirent Note Added: 0015784
08-10-2020 15:55 Jacob Wieland - Spirent Note Added: 0015785
07-12-2020 13:18 Jacob Wieland - Spirent File Added: CR7862-5.docx
07-12-2020 13:19 Jacob Wieland - Spirent Status confirmed => new
07-12-2020 13:20 Jacob Wieland - Spirent Note Added: 0015797
07-12-2020 13:20 Jacob Wieland - Spirent Assigned To Jacob Wieland - Spirent => Tomas Urban
07-12-2020 13:20 Jacob Wieland - Spirent Status new => confirmed
09-12-2020 08:02 Tomas Urban Note Added: 0015819
09-12-2020 08:02 Tomas Urban Assigned To Tomas Urban => Kristóf Szabados
09-12-2020 19:11 Kristóf Szabados File Added: CR7862-6.docx
09-12-2020 19:16 Kristóf Szabados Note Added: 0015828
09-12-2020 19:17 Kristóf Szabados Note Added: 0015829
09-12-2020 19:17 Kristóf Szabados Assigned To Kristóf Szabados => Tomas Urban
09-12-2020 19:17 Kristóf Szabados Status confirmed => assigned
10-12-2020 07:33 Tomas Urban Note Added: 0015832
10-12-2020 07:33 Tomas Urban Assigned To Tomas Urban => Jacob Wieland - Spirent
10-12-2020 07:33 Tomas Urban Status assigned => confirmed
10-12-2020 09:21 Jens Grabowski Note Added: 0015839
10-12-2020 09:22 Jens Grabowski Status confirmed => resolved
10-12-2020 09:22 Jens Grabowski Resolution open => fixed
10-12-2020 09:22 Jens Grabowski Assigned To Jacob Wieland - Spirent => Gyorgy Rethy
17-12-2020 16:18 Gyorgy Rethy Assigned To Gyorgy Rethy => Jens Grabowski
17-12-2020 16:18 Gyorgy Rethy Product Version => V1.2.1 (published 2020-05)
17-12-2020 16:18 Gyorgy Rethy Target Version => V1.3.1 (ongoing)
28-12-2020 13:04 Jens Grabowski Status resolved => closed


MantisBT 1.2.14 [^]
Copyright © 2000 - 2024 MantisBT Team
Powered by Mantis Bugtracker