Kotlin / kotlinx.collections.immutable

Immutable persistent collections for Kotlin
Apache License 2.0
1.17k stars 61 forks source link

Expose the implementation #66

Open btj opened 4 years ago

btj commented 4 years ago

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 commented 4 years ago

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

acanthite1855 commented 4 years ago

@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 commented 3 years ago

Related: https://github.com/Kotlin/kotlinx.collections.immutable/issues/106

mcpiroman commented 2 years ago

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 commented 2 years ago

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.

Sporking commented 3 months ago

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 commented 3 months ago

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.