我正在处理一个抽象类和两个具体的类,它们实现了抽象类。下图如下:
我的课程如下:
abstract class NavItem() {
var attributes: String = ""
var text = ""
}
class NavMenu(val items: MutableList<NavItem>) : NavItem()
class NavLink(var shortText: String) : NavItem()
问题是,当我尝试使用可能是NavMenu或NavLinks的项目时,NavMenus有一个NavLinks集合。
我正在尝试使用多态性作为下一个代码的项目:
navMenu.items.forEach{ item ->
buildNavItem(item)
}
buildNavItem方法似乎是:
private fun buildNavItem(navMenu: NavMenu){
navMenu.items
navMenu.attributes
navMenu.items
}
private fun buildNavItem(navItem: NavItem){
navItem.text
navItem.attributes
}
private fun buildNavItem(navLink: NavLink){
navLink.text
navLink.attributes
}
但是代码总是进入buildNavItem(navItem:NavItem)中,即使在每个代码中我有时也会看到该项目是NavLink或NavMenu。
有什么建议吗?
谢谢!
答案 0 :(得分:3)
这不是多态的工作原理。您拥有navMenu.items
类型的MutableList<NavItem>
列表,它可以存储NavItem
或其后代。在forEach
函数中,您将浏览具有NavItem
类型的每个项目,然后调用buildNavItem(item)
函数。在这种情况下,总是调用buildNavItem(navItem: NavItem)
。要使用另一个参数调用同一方法,您需要将其显式转换为该类型。我建议(即多态性如何工作)是在buildNavItem()
类中创建NavItem
函数,并在后代中实现它:
abstract class NavItem() {
var attributes: String = ""
var text = ""
abstract fun buildNavItem()
}
class NavMenu(val items: MutableList<NavItem>) : NavItem() {
override fun buildNavItem() {
// ... your concrete implementation for NavMenu
}
}
class NavLink(var shortText: String) : NavItem() {
override fun buildNavItem() {
// ... your concrete implementation for NavLink
}
}
然后您可以在forEach
函数中调用它:
navMenu.items.forEach { item ->
item.buildNavItem()
}
在那种情况下,将为存储在buildNavItem()
中的正确对象调用navMenu.items
函数,即,如果它是NavLink
类型的对象,则函数'buildNavItem()'在NavLink
类中重写的,将被调用。
答案 1 :(得分:-1)
问题:
navMenu.items.forEach { item ->
item.buildNavItem()
}
由于items
的类型为List<NavMenu>
,因此编译器将调用适用于类型item
的{{1}}的函数,在这种情况下,重载将导致NavMenu
。
解决方案:
为了调用更具体的重载,编译器需要知道类型。您可以智能地投射项目,然后调用适当的函数:
NavMenu
通过这种方式,只要您调用private fun buildNavItem(navMenu: NavMenu) {
when(navMenu){
is NavItem -> buildNavItem(navMenu) // navMenu is smart casted to NavItem
is NavLink -> buildNavItem(navMenu) // navMenu is smart casted to NavLink
else -> throw IllegalStateException("Unknown subtype ${navMenu::class.simpleName} of NavMenu")
}
}
,就可以委派给适当的函数。