如何以多态方式处理对象列表?解决JVM类型擦除下扩展函数冲突问题
方案1:封装列表为实体类型实现多态
直接绕过泛型擦除的问题,把不同类型的动物列表封装成独立的类,实现共同的列表接口,天然支持多态调用。
// 定义动物列表公共接口 interface AnimalList { fun sayHello(): String } class CatList(val list: List<Cat>) : AnimalList { override fun sayHello() = "Hello, we are a herd of cats" } class DogList(val list: List<Dog>) : AnimalList { override fun sayHello() = "Hello, we are a pack of dogs" } fun printGreeting(animals: AnimalList) { println(animals.sayHello()) }
调用示例:
val cats = CatList(listOf(Cat(), Cat())) val dogs = DogList(listOf(Dog(), Dog())) printGreeting(cats) // 输出 Hello, we are a herd of cats printGreeting(dogs) // 输出 Hello, we are a pack of dogs
该方案类型安全,编译期即可完成校验,无运行时开销,适合列表元素类型统一的固定场景。
方案2:运行时类型判断实现扩展函数
如果不想封装新的列表类型,可以直接给List<Animal>写扩展函数,运行时判断元素类型走对应逻辑:
fun List<Animal>.sayHello(): String { return when { all { it is Cat } -> "Hello, we are a herd of cats" all { it is Dog } -> "Hello, we are a pack of dogs" else -> "Hello, we are a group of mixed animals" } } fun printGreeting(animals: List<Animal>) { println(animals.sayHello()) }
调用示例:
printGreeting(listOf(Cat(), Cat())) // 输出 Hello, we are a herd of cats printGreeting(listOf(Dog(), Dog())) // 输出 Hello, we are a pack of dogs printGreeting(listOf(Cat(), Dog())) // 输出 Hello, we are a group of mixed animals
该方案不用修改原有代码结构,直接兼容原生List类型,缺点是存在运行时检查开销,新增动物类型需要同步修改扩展函数的判断逻辑。
方案3:访问者模式(适合多操作扩展场景)
如果后续需要给不同动物列表扩展更多操作,比如统计食量、计算活动空间等,可以用访问者模式解耦操作和类型:
// 访问者接口 interface AnimalVisitor { fun visit(cats: List<Cat>): String fun visit(dogs: List<Dog>): String } // 给Animal添加accept方法 interface Animal { fun sayHello(): String fun accept(visitor: AnimalVisitor, list: List<Animal>): String } class Dog: Animal { override fun sayHello() = "Hello, I'm a dog" override fun accept(visitor: AnimalVisitor, list: List<Animal>) = visitor.visit(list.filterIsInstance<Dog>()) } class Cat: Animal { override fun sayHello() = "Hello, I'm a cat" override fun accept(visitor: AnimalVisitor, list: List<Animal>) = visitor.visit(list.filterIsInstance<Cat>()) } // 实现问候操作的访问者 class GreetingVisitor : AnimalVisitor { override fun visit(cats: List<Cat>) = "Hello, we are a herd of cats" override fun visit(dogs: List<Dog>) = "Hello, we are a pack of dogs" } fun printGreeting(animals: List<Animal>) { if (animals.isEmpty()) return val visitor = GreetingVisitor() println(animals.first().accept(visitor, animals)) }
该方案新增操作不需要修改动物类的代码,符合开闭原则,适合业务逻辑复杂、需要频繁扩展列表操作的场景。
内容的提问来源于stack exchange,提问作者J-bob
相关产品推荐
相关产品推荐

