在Smalltalk中在运行时向对象添加特征

时间:2014-11-15 13:43:05

标签: smalltalk traits

对于一个小型大学项目,我需要在Smalltalk中编写一个模拟颁奖仪式的应用程序。在这里,艺术家和乐队可以被提名获奖。但是,个别艺术家也可以成为投票给被提名人的陪审团成员。

为了强制限制不在陪审团中的艺术家不能投票,我想在每个艺术家对象被添加到陪审团后动态添加特征。这允许我适当地处理方法类。

我现在的问题是,是否可以动态地将Traits添加到对象?我已经看过How can I add methods to a class at runtime in Smalltalk?,但实际上并不是我想要的。

此致

更新1 在类侧添加方法后,这是有效的。但是,当我希望将一位艺术家分配给陪审团时,我会写下这样的内容:

kurt_cobain juryMemberOf: aJury.

然后在方法juryMemberOf中我将(投票)艺术家添加到列表中(以跟踪他所属的所有陪审团成员):

juryList add: (VotingArtist from: self)

当我检查juryList时,我确实看到我将VotingArtist对象添加到列表中。但是,我的工作区中的原始Artist对象尚未更改为VotingArtist。不确定这是否可行,但稍后我需要有能力写:

kurt_cobain votesFor: justin_bieber.

此时我得到方法MessageNotUnderstood votesFor,这是正常的,因为kurt_cobain仍然是艺术家对象。

2 个答案:

答案 0 :(得分:2)

那是非常 hacky。你的问题可以用经典继承来解决(我不打算在这里详细说明,因为它是家庭作业)。拥有投票权的艺术家只是一个子类或Artist。如果您想给艺术家投票权,请更改班级,例如VotingArtist from: self,其中VotingArtistArtist的子类。 #from:可以实现为

VotingArtist class>>from: anArtist
    ^ self new copyFrom: anArtist

答案 1 :(得分:1)

不要在向对象添加行为方面考虑问题。根据您将如何使用该行为来考虑它。

在代码中的某个时刻,您需要说

kurt_cobain votesFor: justin_beiber    "How is this even possible?"

此时,你怎么知道kurt_cobain是一个能投票的对象?您是否首先需要测试是否是这种情况?

kurt_cobain canVote ifTrue: [kurt_cobain votesFor: justin_beiber]

如果您在任何地方都这样做,那么您实际上一直在进行课堂测试。类测试是一种代码味道,你会丢失对象。

相反,请考虑使用VotingArtist的建议。每当您使用VotingArtist时,您都会知道您正在谈论可以投票的人。没有必要测试课程。 VotingArtist将引用艺术家并且还可以跟踪VotingArtist提名或投票的人。也许该活动有一系列艺术家和另一个投票艺术家的集合。你永远不会要求艺术家投票,你也不会要求投票艺术家表演。但是,投票艺术家可能会引用一位艺术家。

那么,现在问题是,VotingArtist是否应该回应与艺术家相同的消息?在您希望使用艺术家的情况下,您会使用VotingArtist吗?这里的答案很可能是否定的。投票艺术家投票并提名。艺术家表演音乐。如果您想发送与表演音乐相关的消息,并且您在知道自己有VotingArtist的情况下,请向VotingArtist询问其艺术家并将其用于表演音乐行为。 VotingArtist和Artist之间可能没有任何行为重叠,因此甚至没有子类关系。如果两者都不可互换使用,则两者之间不需要层次关系。