Skip to content
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

Class Declaration: final keyword #3852

Open
staycoolcall911 opened this issue Aug 17, 2023 · 9 comments
Open

Class Declaration: final keyword #3852

staycoolcall911 opened this issue Aug 17, 2023 · 9 comments
Labels
🛠️ compiler Compiler 📜 lang-spec-impl Appears in the language spec roadmap

Comments

@staycoolcall911
Copy link
Contributor

The final keyword on a class indicates that this class cannot be extended.

@staycoolcall911 staycoolcall911 added 📜 lang-spec-impl Appears in the language spec roadmap 🛠️ compiler Compiler labels Aug 17, 2023
@Chriscbr
Copy link
Contributor

Chriscbr commented Aug 17, 2023

What if we make classes final-by-default? Kotlin, another popular object-oriented language derived from Java, takes this choice to encourage explicitly documenting support for inheritance as an "opt-in" choice by library authors instead of opt-out:

class Foo {} // I can't inherit it
open class Bar {} // I can inherit it

See this stackoverflow post for more details. I think it might align with our language's philosophy of good cognitive friction.

For interoperability with JSII, we'd have to assume any existing JSII classes from TypeScript are still open since TypeScript/JSII doesn't have a convention for specifying final classes AFAIK.

@MarkMcCulloh
Copy link
Contributor

What if we make classes final-by-default?

I'm into that, considering wing also generally favors immutable-by-default behaviors. I assume the same would apply to interfaces and structs?

@yoav-steinberg
Copy link
Collaborator

The down side (but this might also be an up side) is when you want to inherit something from some library and there's no real bad reason not to allow this except that the lib's author didn't put the open keyword.
Even if you go through the pain of doing a PR for that lib, it'll trigger a whole philosophical debase whether that class should be open or not.

@Chriscbr
Copy link
Contributor

@yoav-steinberg Right. I think it's a similar kind of tradeoff as wanting to use a class's private field as if it were public.

@MarkMcCulloh Good question. For structs I could see a line of reasoning that when a struct extends another struct, it more closely resembles composition, since you're just adding one bag of fields to another. No code or "behavior" is getting layered through super calls, so there isn't the same risk as when you extend a class that wasn't designed to be extended. So from that angle I'm not sure if the distinction between open and closed structs is as useful. But I'm not sure. Same goes for interfaces.

@yoav-steinberg
Copy link
Collaborator

yoav-steinberg commented Aug 17, 2023

My opinion here is not only to be open by default, but also not to bother adding a final to the lang. I'm aware of the risks in this but I think it's a matter of practicality. And in practice deriving a class can be very useful and beautiful and it's hard to "design" something as final or not. While making a member private or public feels like something easier to design and then debate about when we feel like we need to change the design.
(not strongly opinionated here though)

@olivernybroe
Copy link
Contributor

olivernybroe commented Aug 18, 2023

I prefer closed by default and then open keyword.
It adds some safety to our code and makes it only be used as intended.

@ShaiBer
Copy link
Contributor

ShaiBer commented Aug 21, 2023

I'm with @yoav-steinberg in this, especially because of the need to extend external libs

The down side (but this might also be an up side) is when you want to inherit something from some library and there's no real bad reason not to allow this except that the lib's author didn't put the open keyword.
Even if you go through the pain of doing a PR for that lib, it'll trigger a whole philosophical debase whether that class should be open or not.

My opinion here is not only to be open by default, but also not to bother adding a final to the lang. I'm aware of the risks in this but I think it's a matter of practicality. And in practice deriving a class can be very useful and beautiful while and it's hard to "design" something as final or not. While making a member private or public feels like something easier to design and then debate about when we feel like we need to change the design.
(not strongly opinionated here though)

@github-actions
Copy link

Hi,

This issue hasn't seen activity in 60 days. Therefore, we are marking this issue as stale for now. It will be closed after 7 days.
Feel free to re-open this issue when there's an update or relevant information to be added.
Thanks!

Copy link

github-actions bot commented Mar 3, 2024

Hi,

This issue hasn't seen activity in 90 days. Therefore, we are marking this issue as stale for now. It will be closed after 7 days.
Feel free to re-open this issue when there's an update or relevant information to be added.
Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🛠️ compiler Compiler 📜 lang-spec-impl Appears in the language spec roadmap
Projects
Status: 🤝 Backlog - handoff to owners
Status: Todo - out of scope for beta
Development

No branches or pull requests

6 participants