问题一:在 SqlVisitor 抽象类中,为什么需要为不同的 SqlNode 子类定义不同的 visit 方法?
在 SqlVisitor 抽象类中,为什么需要为不同的 SqlNode 子类定义不同的 visit 方法?
参考回答:
在 SqlVisitor 抽象类中为不同的 SqlNode 子类定义不同的 visit 方法,是为了实现访问者模式的核心思想——双分派。这样做允许访问者在访问不同类型的节点时执行不同的逻辑。当 SqlNode 对象的 accept 方法被调用时,它会根据对象的实际类型调用 SqlVisitor 中相应的 visit 方法,从而实现多态行为。这种设计使得 SQL 结构的解析和转换更加灵活和可扩展。
关于本问题的更多回答可点击原文查看:
https://developer.aliyun.com/ask/672299
问题二:为什么每个类的 accept 方法内容相同,但不能直接写在父类 SqlNode 中?
为什么每个类的 accept 方法内容相同,但不能直接写在父类 SqlNode 中?
参考回答:
每个类的 accept 方法内容相同,但不能直接写在父类 SqlNode 中,因为这样做会导致所有的 accept 调用都指向 SqlVisitor 中的 visit(SqlNode) 方法(如果该方法存在的话)。由于 Java 的重载是在编译时根据方法的参数类型决定的,而 this 在 accept 方法中的编译时类型是 SqlNode,因此无论实际运行时的对象是哪个子类,都会调用到 visit(SqlNode),从而忽略了具体的子类类型,导致其他重载的 visit 方法形同虚设,不符合预期。
关于本问题的更多回答可点击原文查看:
https://developer.aliyun.com/ask/672300
问题三:如果尝试在 SqlVisitor 中添加 visit(SqlNode) 方法会怎样?
如果尝试在 SqlVisitor 中添加 visit(SqlNode) 方法会怎样?
参考回答:
如果尝试在 SqlVisitor 中添加 visit(SqlNode) 方法,虽然可以通过编译,但会导致所有通过 accept 方法调用的 visit 都会指向这个 visit(SqlNode) 方法,因为 this 在 accept 方法中的编译时类型是 SqlNode。这样,无论 SqlNode 的实际子类是什么,都会执行这个通用的 visit(SqlNode) 方法,无法利用到具体子类的特性,程序的运行结果将不符合预期。
关于本问题的更多回答可点击原文查看:
https://developer.aliyun.com/ask/672301
问题四:Java 的重载为什么被称为“编译期多态”?
Java 的重载为什么被称为“编译期多态”?
参考回答:
Java 的重载被称为“编译期多态”,是因为重载的方法在编译时就已经根据方法的参数类型、参数数量和参数顺序确定了调用哪个方法。这种多态性是在编译时就确定的,与运行时的对象实际类型无关。因此,即使 this 在运行时指向的是 SqlNode 的子类对象,由于 accept 方法中的 this 在编译时的类型是 SqlNode,所以调用 visit(this) 时也会根据 SqlNode 类型来匹配 SqlVisitor 中的方法。
关于本问题的更多回答可点击原文查看:
https://developer.aliyun.com/ask/672302
问题五:动态语言在实现访问者模式时有什么优势?
动态语言在实现访问者模式时有什么优势?
参考回答:
动态语言在实现访问者模式时具有优势,因为它们通常支持运行时多态(也称为动态多态),这意味着方法的调用是在运行时根据对象的实际类型来决定的。这种特性使得在动态语言中实现访问者模式时,可以更加直接和简单地根据对象的实际类型来调用相应的 visit 方法,而无需像 Java 那样在编译时就确定方法调用。此外,一些支持模式匹配的函数式程序设计语言还可以进一步简化访问者模式的实现,使得代码更加清晰和易于维护。
关于本问题的更多回答可点击原文查看: