Kotlin中如何约束泛型?限定PublishSubject接收可食用水果
Great question! Let's break this down and find a clean, type-safe solution without subclassing PublishSubject.
First, your initial attempt PublishSubject<Fruit : Edible> uses invalid Kotlin syntax for generic constraints. What you need is a way to enforce that the stream only accepts types that are both Fruit and Edible. Kotlin supports this with intersection types, denoted by the & operator.
Correct Implementation
Here's how to create your stream with the exact constraint you want:
// Create a PublishSubject that only accepts types which are Fruit AND Edible val stream = PublishSubject.create<Fruit & Edible>()
This works because:
- The
Fruit & Edibleintersection type tells the compiler that only objects implementing bothFruit(or its subclasses) andEdibleare allowed in the stream. - Your
Appleclass (which extendsFruitand implementsEdible) will be accepted without issue. - Non-
FruitEdibletypes (likeIceCreamorPotato) will be rejected at compile time, as willFruitsubclasses that don't implementEdible.
Simplify with a Type Alias
If you need to reuse this constrained type across multiple places, define a type alias to keep code clean:
// Define a reusable alias for types that are both Fruit and Edible typealias EdibleFruit = Fruit & Edible val stream = PublishSubject.create<EdibleFruit>()
Why Avoid the Filter Approach?
Your initial idea of PublishSubject<Edible>.create().filter { it is Fruit } is not ideal because:
- It relies on runtime checks instead of compile-time type safety. Invalid objects can still be sent to the stream (they'll just be filtered out later), which hides potential bugs.
- It's less efficient, as it requires processing every
Edibleobject even if it's not aFruit.
Key Takeaway
Using Kotlin's intersection types gives you compile-time enforcement of your dual constraint, no subclassing required. This is the most idiomatic and safe way to achieve your goal with RxJava in Kotlin.
内容的提问来源于stack exchange,提问作者Arturs Vancans

