假设我有这个简单的界面:
interface Y { Y f(); }
我可以通过 3 种不同的方式实现它:
到处使用通用类型。
class SubY_generalist implements Y{ public Y f() { Y y = new SubY_generalist(); ... return y; } }
使用特殊类型,但返回相同的值,隐式转换为通用类型。
class SubY_mix implements Y{ public Y f() { SubY_mix y = new SubY_mix(); ... return y; } }
使用特殊类型并返回相同的值。
class SubY_specialist implements Y{ public SubY_specialist f() { SubY_specialist y = new SubY_specialist(); ... return y; } }
这里附近有一个关于“接口编程”好处的长篇对话。最受推崇的答案似乎并没有深入探讨参数类型和返回类型之间的区别,它们实际上是根本不同的。因此,我发现其他地方的讨论并没有给我一个明确的答案,我别无选择,只能自己推测——当然,除非好心的读者能帮我一把。
我将假设以下有关 Java 的基本事实:(它们正确吗?)
一个物体是在其最特殊的时候被创建的。
它可以随时隐式转换为更通用的类型(广义的) 。
当一个对象被泛化时,它会失去一些有用的属性,但不会获得任何属性。
从这些简单的观点来看,特殊物体比一般物体更有用,但也更危险。
例如,我可能有一个可变容器,我可以将其概括为不可变。如果我确保容器在被冻结之前具有一些有用的属性,我可以在正确的时间对其进行概括,以防止用户意外破坏不变量。但这是正确的方法吗?还有另一种方法可以实现类似的隔离:我可能总是将我的方法设为package-private。泛化似乎更灵活,但很容易被忽略,并为微妙的错误引入一个表面。
但在某些语言中,比如 Python,人们认为没有必要真正保护方法免受外部访问;他们只是用下划线标记内部方法。熟练的用户可以访问内部方法来获得一些收益,只要他们了解所有的复杂性。
另一个结果是,在方法定义中我应该更喜欢专门的对象。
这是正确的想法吗?
我错过了什么吗?
这与接口编程的讨论有何关系?这里的一些当地人似乎认为这是相关的,我也同意这一点,只是在我看来不是立即发生的。它更像是针对接口进行编程,或者通常针对子类进行编程。我对这些错综复杂的事情有点不知所措。
慕村9548890
相关分类