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

Expose the implementation #66

Open
btj opened this issue Dec 19, 2019 · 7 comments
Open

Expose the implementation #66

btj opened this issue Dec 19, 2019 · 7 comments

Comments

@btj
Copy link

btj commented Dec 19, 2019

The current proposal document is undecided about whether to expose implementation types in the API. I'm confused about that. If only interface types are exposed, how can consumers be sure the collection objects they are dealing with are really immutable? Relying on adherence to the contract seems fragile. A buggy "smart" custom implementation can cause hard-to-diagnose problems far from the source of the error. It defeats the encapsulation benefits of using immutable types in APIs.

@btj
Copy link
Author

btj commented Dec 19, 2019

Or, expose an abstract superclass that can be implemented only by the standard library.

@acanthite1855
Copy link

acanthite1855 commented Apr 18, 2020

@btj I'm 100% agree with you. Standard library collections have this problem. But that's fine, List<T> is not supposed to be immutable, but rather provide a read-only view of a list. So I though maybe some immutable collections exist in kotlin and found this lib. I was so happy installing the new fancy immutables into my project. But what my disappointment was when I found out that whole library is build around interfaces.
The whole thing is about being sure no one can modify the collection from the outside, and then we are given interfaces... 😐

Regarding the solution to the problem. As for me, the approach of C# System.Collections.Immutable seems to be good. Though, they also have interfaces, the implementations are public and final and used all over the place in factory and builder return types.

@qurbonzoda
Copy link
Contributor

Related: #106

@mcpiroman
Copy link
Contributor

mcpiroman commented Jan 17, 2022

I do want to be able to write my own implementation for (some) immutable collections and thus I'd like to keep the interface approach, at least a thin abstract classes fwiw.

Someone can write and use implementation for ImmuableCollection that is not truhly immutable or otherwise buggy but it's not somethink specific to this library. Someone could write buggy implementation for List<T> as well. We'd have to ban all interfaces.

@rhdunn
Copy link

rhdunn commented Oct 8, 2022

I'm in favour of having interfaces because then you are not tied to specific immutable implementations in your APIs (e.g. you could have different classes implementing sublists, map keys, etc.).

I have a project where the persistent set interface is useful for a class I'm creating that would then be backed by a persistent set -- specifically, the add, remove, and contains logic is slightly different to a standard set as the elements can be combined or split in those operations. At the moment, I'm using the Kotlin Set interface with custom methods to provide the add/remove/clear persistent operations.

An example similar what I'm doing would be a set of ranges, where adding overlapping ranges would replace those two ranges with a single range over the combined range, etc.. There, you would want a custom PersistentSet implementation to handle that additional complexity.

This was referenced Jun 6, 2024
@Sporking
Copy link

Sporking commented Jun 27, 2024

If someone wants to create their own "immutable" list, they can implement the List interface and do what they like.

However, I also want there to be an ImmutableList class (not interface) which has the important property that it CANNOT be inherited from, and which has a known implementation which has known and unchangeable behavior, so that I can be sure that functions that I write that take parameters of that class type are always dealing with immutable data that can't be altered asynchronously by an attacker. This is a security issue! (This is also why Guava implements immutable data structures as classes, not interfaces, and why java.util.String, java.util.Integer, etc. are final classes, not interfaces.)

There are multiple bug reports asking for true immutable classes (not just interfaces that promise that their implementations will be immutable.) See for instance here and here and here.

In the meantime, you can use Guava with some extension functions, as I documented here.

@amal
Copy link

amal commented Jun 27, 2024

It has already been noted that Guava's ImmutableList is not really final.

If an attacker already has access to the runtime, you can never guarantee that the implementation has absolutely unchangeable behavior and will not be mocked in any way. Regardless of whether the class is final or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants