我的团队今天对var属性和对象复制有争议。我们有一个用于RecyclerView的适配器。适配器采用ItemModel列表,该列表具有一些属性。单击任何项目时,我们需要更改单击项目的属性值。
有人说我们应该将该属性设为var。因此,我们可以为其分配新值。
有些人说我们应该将属性设为val,并使用ItemModel.copy并将新值传递给副本。但是要做到这一点,我们需要调用List.map来创建一个新列表,因为List是不可变的。这意味着,要更改一项的一个属性值,我们需要遍历整个列表,创建一个包含所有项的新列表以及更改后的项的新副本。
根据我的经验,前一种方法对我而言是正确的,而后一种方法会执行过多不必要的操作,并且会对性能和资源产生不良影响。但是,他们在讨论属性可变性等问题,并声称后者是一种更现代的编程方式。
任何对android和功能编程有深入了解的人都可以为我解释一下是否真的认为更好的方法吗?
答案 0 :(得分:1)
这是您的recyclerview的列表,如果recyclerview应该有效地更改列表项计数(创建或删除),则它应该是可变列表。列表中的val
和var
并不重要(在使用val
的情况下,因为创建,更新或删除项目时无需重新分配列表)。这些操作中的每一个操作都不会重新分配列表对象。它仍然是相同的列表,只是其中包含不同的项目。当您想更改列表中项目编号3的值x时,val
和var
很重要。然后,它(变量x)必须为var
,您才能更改它,但列表没有。
您使用val
表示该值将永远不会更改。这是出于可维护性,因此不会发生奇怪的错误。就像您有另一个对象引用了我们之前讨论过的列表一样。如果列表是var
,则可以在变量上创建一个新列表,现在您的两个对象不再指向同一列表。相反,其中一个仍然指向旧列表。您可能不希望这样,您的程序会中断。因此,只要可行,您都应该使用val
。只要有必要,您就应该使用var
,而不要试图使val
复杂化。除非您有充分的理由(例如,该值无法更改,因为它已在各处被引用),否则您将无法继续进行。那就是当您使用对象复制时。但这并不是所有方法的默认最佳做法。
那只是我对此的看法。
旁注将一个班级标记为data class
将为您生成复制方法。因此,您甚至无需实施复制就可以复制该对象。巫婆真棒!
答案 1 :(得分:0)
将属性设置为var
非常诱人,但是它可能导致错误,即使重现也是如此。当您遍历对一个对象的引用,并且在几个地方使用了它的内容并且可以对其进行更改时,您可能会失去对实际应用程序状态的控制。该代码可能变得不可预测。
不可移植性是功能编程的核心。目的是消除此类漏洞并帮助程序员编写每次都能按预期执行的代码,因为它消除了发生副作用的风险。
但是,正如您和您的团队所注意到的那样,功能方法有时可能需要额外的工作和资源。但是这值得吗?好吧,我不知道该列表应该多大才能通过映射对其产生重大影响。即使当前您的对象未在任何地方共享,您也无法确保将来不会有人更改它。因此,请记住功能方法不太容易出错,我认为这是值得的。
答案 2 :(得分:0)
您应该将值设为var
。
重新创建整个列表(可能包含1000多个项目)以更改一个值是无效的,没有实现任何目的。使问题变得过于复杂并不意味着首先要解决一个难题:)
在您自己的陈述中,您说:When any item is clicked, we need to change a property's value of the clicked item.
<-您不应重新创建或更新整个列表以更新单个项目的单个值,还请考虑以下事实:仅更新一项,您应该调用notifyItemChanged
而不是notifyDataSetChanged
,因为调用notifyItemChanged
更为有效,重新分配或重新创建以及分配整个列表是毫无意义的
答案 3 :(得分:-1)
第二种方法违反了Kotlin的基本设计。
使用Kotlin,您不需要编写与Java中一样多的代码行,例如,包含在类中的get和set函数。为什么要使用一种旨在缩短代码行的语言来使代码更长,更复杂?
另一点是,较长的代码可能难以阅读和维护。
最后一点是,一个类的副本比Var需要更多的资源和时间来创建和访问,对我而言,没有理由将其视为一种很好的方法。