Answers:
使用比将任意数量的值作为名称/值对保存的哈希表更好的定义的类作为返回类型。
首先,最重要的一点是-可维护性。通过查看代码,新程序员永远无法说出该方法返回的值是什么。如果新手无法通过查看代码来理解这些内容,那么当有人要向该数据添加更多键/值或增强应用程序时,该代码将无用且容易出错。
方法是调用者与服务之间的合同。方法中最重要的是它们的输入和输出。此输入和输出应易于阅读和理解,并具有自记录功能。如果您使用Person类作为具有名字,姓氏,年龄的返回值-这是自我记录。如果为此生成了Javadoc,则用户可以在各类之间导航以更好地理解这一点。如果您使用哈希表,则必须在注释中对其进行解释,当情况发生变化时,任何人都不会阅读或更新该哈希表。
HashMap<String,String>
如果要在return语句中添加数字(例如age),则不能使用泛型。如果不使用泛型,则必须在对象与实际类型之间来回转换。如果您使用动态类型,则可以保存。
与在编译时发现问题相比,运行时失败的可能性也更大。例如,如果某人从哈希图中删除了一个条目,而一个旧调用者期望该条目,则客户端在运行期间会失败。最好在编译时捕获此问题。
如果要使用hashmap作为返回类型,则很难返回不可变类型。但是,如果您使用用户定义的自己的类型,则可以控制此类型。
将hashmap用作返回类型将很诱人,因为您可以避免在开始时创建几个类,但是将来维护代码将是一场噩梦。面向对象!!!
问题之一是,在许多情况下,哈希表的键是字符串。因此,该方法的使用者必须事先知道要使用哪些键来提取数据。在访问数据时,这可能会由于拼写错误而产生错误。
另一个缺点是可重构性。如果您以后决定更改成员的名称,那么您将有一堆需要更改的魔术字符串。使用大多数优秀IDE所提供的重构工具来重命名类成员要容易得多。使用哈希表,您可能必须对所有源文件进行查找/替换操作,这可能会出现问题。
最后,您将失去对成员访问权限的编译时检查-无论是名称还是类型。如果您的哈希表仅包含一种类型的对象,但如果它包含许多类型的对象(即使在同一层次链中),那么后者就不是问题,您真的想利用语言的类型系统并在那里进行编译时检查。在大多数IDE中,您将具有某种智能/自动完成功能-这些功能可以通过查看类型系统来实现,但它们将无法为您提供哈希表键。
至于时候,它会是适当返回一个哈希表(或键值对其他类似的集合),当这两个值,你可以使用这个和按键并不在编译时已知。例如,如果您有一个解析查询字符串并返回键和对应值的方法,则哈希表将是一个不错的选择。在这种情况下,您还需要考虑返回某种不可变或只读哈希表。
编辑 -在谈论动态语言时,此答案中提出的大多数观点不再适用:)
对此最重要的论据是您向消费者暴露了太多信息。消费代码只需要知道它是某种键值集合(字典)即可;无论是将其实现为哈希图,关联列表,特里还是任何东西,都相对没有意思。因此,正确的方法是通过合适的接口(IDictionary
或您选择的语言使用的任何值)而不是实际类型返回。
所有这一切都假定您实际上需要一个字典来表示数据,即,您的数据由键/值对组成,其中键在数据集中是唯一的,并且不能在编译时固定。如果您具有预先知道的密钥,则应该为数据创建一个适当的类型(或根据需要创建多个)。这取决于您是否将密钥本身视为数据的一部分或代码的一部分。
编辑:
为了澄清起见,我在这里使用术语字典来表示键值数据结构的最通用类型。我的意思不是任何特定于语言的实现,例如Python dict
或.NET Dictionary
。
我会问自己一个问题:“此词典中的键是否正在更改?” 如果它们是常量,则应返回一个对象或其他适当的数据结构。如果它们是动态的,则您可能需要返回某种字典样式结构。最后,如果有一些将保持不变的键和一些未知的动态键集,则您可能希望返回一个混合数据结构,包括一些固定值和某种针对溢出的字典。