如何从超类中访问子类方法?超类含Switch调用子类创建方法
嗨,这个问题问得很典型,咱们一步步捋清楚哈~
首先直接给结论:默认情况下,超类是不能直接访问子类特有的方法的。因为超类在设计的时候,根本无法预知子类会新增哪些专属方法——面向对象的核心思想里,超类是子类的抽象,子类是超类的具体实现,反过来依赖就搞反了逻辑。
看你给出的代码片段,你在超类的函数里通过switch调用不同子类的createCityOne()、createCityTwo()这类方法,这种写法其实是有问题的:
if transitionSprite.name == nil || transitionSprite.name == "rd-d2c" || transitionSprite.name == "rd-f2c" || transitionSprite.name == "rd-c2c" {
print("city should come next")
switch randomIndex {
case 0: cityOne.createCityOne() print("1")
case 1: cityTwo.createCityTwo()
...
}
}
这里超类直接持有了子类的实例(cityOne、cityTwo),还依赖了子类的专属方法,会带来两个大问题:
- 代码耦合度极高:以后新增
CityThree、CityFour,你必须修改超类里的switch分支,完全违反了开闭原则(对扩展开放,对修改关闭)。 - 违背了面向对象的设计逻辑:超类应该只关注通用逻辑,不该插手子类的具体实现细节。
更好的解决方案:用多态替代switch
咱们可以用多态的思路重构代码,彻底解决这个问题:
在超类中定义通用的抽象方法
在你的超类里声明一个所有子类都需要实现的通用方法,比如createCity(),Swift里可以这么写(其他语言逻辑类似):class SuperCityClass { func createCity() { // 强制子类重写该方法,否则运行时报错 fatalError("子类必须重写createCity方法") } // 你原来包含switch的处理函数 func handleTransition(transitionSprite: Sprite) { let validNames = ["rd-d2c", "rd-f2c", "rd-c2c"] if transitionSprite.name == nil || validNames.contains(transitionSprite.name!) { print("city should come next") // 直接调用通用方法,不需要switch! createCity() } } }子类重写通用方法
每个子类去重写createCity(),把原来的createCityOne()、createCityTwo()的逻辑放进去:class CityOne: SuperCityClass { override func createCity() { // 原来createCityOne()的所有业务逻辑 print("1") } } class CityTwo: SuperCityClass { override func createCity() { // 原来createCityTwo()的所有业务逻辑 print("2") } }调用时自动匹配子类实现
当你创建子类实例并调用handleTransition()时,会自动执行对应子类的createCity()逻辑,完全不需要在超类里写switch判断——以后新增子类,只需要重写createCity(),超类的代码一行都不用改!
这样既符合面向对象的设计原则,又让代码更易维护、扩展。
内容的提问来源于stack exchange,提问作者Dave

