Skip to content

Mention relation of interfaces to member fields #3104

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

christoph-ehm
Copy link

In D the interfaces are special abstract classes which forbid non-static function declarations and non-static member field definitions.
For good software engineering reasons I didn't add alias to the interface example.

In D the interfaces are special abstract classes which forbid non-static function declarations and non-static member field definitions.
For good software engineering reasons I didn't add `alias` to the interface example.
@dlang-bot
Copy link
Contributor

Thanks for your pull request and interest in making D better, @christoph-ehm! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

@@ -4,8 +4,9 @@ $(SPEC_S Interfaces,

$(HEADERNAV_TOC)

$(P An $(I Interface) describes a list of functions that a class which inherits
from the interface must implement.)
$(P An $(I Interface) abstracts from a common set of behaviour. It's an abstract class
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$(P An $(I Interface) abstracts from a common set of behaviour. It's an abstract class
$(P An $(I Interface) abstracts common behaviour. It's an abstract class

$(P An $(I Interface) describes a list of functions that a class which inherits
from the interface must implement.)
$(P An $(I Interface) abstracts from a common set of behaviour. It's an abstract class
which doesn't expose implementation details of methods and object state.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and the previous sentence should probably be joined together. The "it's" is a bit jarring.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe: "An Interface abstracts from behaviour in terms of an abstract class which ..."

I originally intended to use simple English but less text is surely reasonable as long as it's comprehensible.

If you have write access to this PR, you are welcome to do the change. I can do this only later on another device.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maxhaton I integrated your changes with my ones.

@mdparker
Copy link
Member

IMO, this is not the best approach to describing interfaces in D. An interface isn't inherited, it's implemented. And they aren't really abstract classes---all classes are subclasses of Object, but interfaces are not. The language used in this PR is potentially confusing.

@christoph-ehm
Copy link
Author

IMO, this is not the best approach to describing interfaces in D. An interface isn't inherited, it's implemented. And they aren't really abstract classes---all classes are subclasses of Object, but interfaces are not. The language used in this PR is potentially confusing.

You are right that I deviate from the common terminology. I did just because of simplicity for learners. The concept of an interface actually is a special type of abstract class and in D the trait isAbstractClass!(MyInterface) is true. By describing interfaces as abstract classes, it indirectly conveys that fact to newbies.

Since there is no syntactical difference between implementing an interface or extending a class (as borrowed from C++ which uses classes to represent interfaces), it would be good to have a general term for both, which I called "inheritance". Maybe there is a different technical term?

@mdparker
Copy link
Member

Maybe there is a different technical term?

Classes in D are more akin to those of Java than C++. There, interfaces are usually "implemented" rather than "inherited". Though really, I suppose "inherit" also works. We inherit both the interface and the implementation from a class, and we inherit the interface from an interface. So I shouldn't have objected to that.

The abstract class bit though just has to go. Abstract classes and interfaces are distinct in D, so that term doesn't work in describing interfaces.

because of simplicity for learners

What we should strive for is clarity, not tutorial level text. The spec is the language definition, not a tutorial.

But I do agree that the first bullet point needs to be revised. First, it could be better worded. Perhaps something like this:

"An Interface is a set of functions that have no implementation. Classes that inherit from an Interface must provide an implementation for each function."

I think this makes the text clearer and gets the point across that an interface is like an abstract class, but without introducing the detour into describing abstraction. However, it's not the whole picture. Further down the page, we see a reference to final and static member functions, which means some functions do have implementations.

With that in mind, I might rewrite the introductory paragraph as:

"An Interface generally is a set of functions that have no implementation. Classes that inherit from an Interface must provide an implementation for each unimplemented function. Interfaces may be specialized to provide final or static member function implementations, and include static member fields."

I think that would be a good start.

The addition you have about non-static member fields is probably backwards. There is nothing in the current documentation that says anything about static member fields. I think it better to add a paragraph that says something like this:

"Interfaces may have static member variables. Non-static member variables are prohibited."

===========

The above refers to your PR, but while you're at it, there are some more improvements to be made on the existing documentation. A couple that would fit in your PR, IMO:

Item 7 in the existing documentation is really poorly worded:

Virtual interface member functions do not have implementations. Interfaces are expected to implement static or final functions.

Ugh! In line with my suggestion about member variables:

"Interfaces may provide implementations of functions, but such functions must be marked as static or final.`

And item 8 in the existing docs:

Interfaces can have function templates in the members. All instantiated functions are implicitly final.

Double ugh! How about:

"Interface functions can be template functions. All such functions are implicitly final, so the interface must provide an implementation."

=====

If you can modify your branch with the changes I've suggested, and also make the additions I've recommended, then I'll have no problem approving it and, barring any further objections, merging it.

Also, please use American spelling for consistency with the rest of the documentation. So, "behavior" instead of "behaviour".

Copy link
Member

@mdparker mdparker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my earlier remarks.

in the introductory paragraph
Corrected static-override example.
Example for behaviour with conflicting symbols.
Example for templated non-static member field.
@christoph-ehm
Copy link
Author

christoph-ehm commented Oct 19, 2021

The abstract class bit though just has to go. Abstract classes and interfaces are distinct in D, so that term doesn't work in describing interfaces.

Only syntactically distinct, but conceptionally the abstract class is a superset of an interface.

Just that classes probably can't inherit multiple abstract classes in D. The Dlang documentation for class is nowhere explicit about multiple inheritance.

Interfaces probably are even implemented as an abstract class under the hood because of isAbstractClass!(InterfaceType).
Anyone who played around with interfaces in D should notice that an interface behaves like an abstract class just with restrictions, which are: no definition for instance members (no declaration for instance fields), required implementation for class members and implemented functions are always final (for whatever reason, more terrible: the attribute can be omitted for templated and static functions).

because of simplicity for learners

What we should strive for is clarity, not tutorial level text. The spec is the language definition, not a tutorial.

Yes, more clarity has been the motiviation for this pull request.

Explanations and hints shouldn't be dismissed as "tutorials". D is known to have (too) technical and terse documentation for beginners which makes D hard to learn and additionally decreases the popularity of Dlang. A documentation should simplify learning. D's community should be interested in improved explanations.

Documentation is the right place for design reasons (except for the reason of subjective taste). People do ask questions in the Forum due to that.

"An Interface is a set of functions that have no implementation. Classes that inherit from an Interface must provide an implementation for each function."

That's equal to the previous text with only different grammar. Frankly, I don't care about grammar unless it's ambiguous or meaningless. I removed the wording because it is what I found unclear by myself and even wrong. My purpose for this PR is that an interface is not just a set of functions in D, not even the general concept is. It's a lightweight abstract class introduced as a simple solution for the diamond problem.

The addition you have about non-static member fields is probably backwards. There is nothing in the current documentation that says anything about static member fields.

Not sure if I understand correctly.
I changed the introductory paragraph (removed "set of functions"). I mentioned "abstract class" so it should be clear by default that members would be allowed in an interface. I added the paragraph about non-static member fields therefore. Example now contains member field templates. All of my added examples are tested with latest rdmd online.

...there are some more improvements to be made on the existing documentation...

Item 7 in the existing documentation is really poorly worded:

Virtual interface member functions do not have implementations. Interfaces are expected to implement static or final functions.

Ugh! In line with my suggestion about member variables:

"Interfaces may provide implementations of functions, but such functions must be marked as static or final.`

Done

Interfaces can have function templates in the members. All instantiated functions are implicitly final.

Double ugh! How about:

"Interface functions can be template functions. All such functions are implicitly final, so the interface must provide an implementation."

Done

Also, please use American spelling for consistency with the rest of the documentation. So, "behavior" instead of "behaviour".

Done

@christoph-ehm
Copy link
Author

christoph-ehm commented Oct 23, 2021

Oh snap. Seems like something changed. Suddenly code is broken with std.traits.isAbstractClass so that it doesn't accept interfaces anymore. I remember that some of my code compiled one or two weaks ago but now doesn't anymore because of that. Atila Neves' Concept library is based on this assumption too.

@mdparker
Copy link
Member

Regardless, if it's clarity you want, then you shouldn't use the term "abstract class" in the interface documentation. Those two words together have a very specific meaning in D, and that meaning is not "interface".

@pbackus
Copy link
Contributor

pbackus commented Mar 10, 2022

D is known to have (too) technical and terse documentation for beginners which makes D hard to learn and additionally decreases the popularity of Dlang. A documentation should simplify learning. D's community should be interested in improved explanations.

Documentation that simplifies learning D for beginners should exist, but the language spec is not the correct place for it.

Broadly speaking, documentation can be divided into four categories: tutorials, HOWTOs, reference documents, and explanatory documents (see the link for more details on these categories).

The language specification is a reference document: its purpose is to be a complete, detailed, and accurate description of the D programming language. It is intended to be used primarily by experienced D programmers who need to look up the specific details of how a particular language feature works. The spec should avoid being unnecessarily obtuse, but correctness and precision are more important than friendliness to beginners.

If you would like to contribute some learning-oriented documentation about D's interfaces, the articles section of dlang.org would be a good place for it.

@dlang-bot dlang-bot removed the stalled label Mar 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants