代码之家  ›  专栏  ›  技术社区  ›  rasilvap

如何处理kotlin中的多态性

  •  2
  • rasilvap  · 技术社区  · 6 年前

    enter image description here

    我的课程如下:

    abstract class NavItem() {
        var attributes: String = ""
        var text = ""
    }
    
    class NavMenu(val items: MutableList<NavItem>) : NavItem()
    
    class NavLink(var shortText: String) : NavItem()
    

    问题是,当我尝试处理可能是NavMenu或NavLinks的项目时,NavMenu有一组NavLinks。

    我正在尝试使用多态性作为下一个代码来处理这些项目:

    navMenu.items.forEach{ item ->
                buildNavItem(item)
            }
    

    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),即使在for-each中,我有时会看到该项是NavLink,或者是NavMenu。

    有什么建议吗?

    谢谢

    2 回复  |  直到 6 年前
        1
  •  5
  •   Sergio    6 年前

    多态性不是这样工作的。你有 navMenu.items 列表的类型 MutableList<NavItem> NavItem 或其后代。在里面 forEach 函数可以遍历每个项目,其中 纳维滕 输入,然后呼叫 buildNavItem(item) 作用在这种情况下 buildNavItem(navItem: NavItem) 他总是被叫来。要使用另一个参数调用同一个方法,需要显式将其转换为该类型。我建议,多态性就是这样工作的,就是创建 buildNavItem() 作用于 类并在子体中实现它:

    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
        }
    }
    

    然后你就可以叫它进来了 弗雷奇 功能:

    navMenu.items.forEach { item ->
            item.buildNavItem()
    }
    

    那样的话 buildNavItem() 函数将为存储在中的正确对象调用 导航菜单项 ,即,如果它是 NavLink 然后键入函数“buildNavItem()”,在中被重写 导航链接 类,将被调用。

        2
  •  -1
  •   Willi Mentzel user670265    6 年前

    问题:

    navMenu.items.forEach { item ->
        item.buildNavItem()
    }
    

    items 是一种 List<NavMenu> ,编译器将调用适用于 item 类型 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")
       }
    }
    

    buildNavItem ,您将委托给相应的功能。