你为什么要用伊娃? [英] Why would you use an ivar?

查看:137
本文介绍了你为什么要用伊娃?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通常会以另一种方式看到这个问题,例如每个人都必须这样做是一个属性?(我喜欢bbum对这个Q的回答)。



我几乎只在我的代码中使用属性。然而,每隔一段时间,我就与一位长期在iOS上开发并且是传统游戏程序员的承包商合作。他编写的代码几乎没有声明任何属性,并且依赖于ivars。我认为他这样做是因为1.)他已经习惯了,因为在Objective C 2。0(2007年10月)和2)之前,属性并不总是存在,因为不能通过getter / setter获得最小的性能增益。



虽然他写的代码没有泄漏,但我仍然希望他使用ivars上的属性。我们谈到了它,他或多或少看不到使用属性的理由,因为我们没有使用KVO,而且他在处理内存问题方面经验丰富。



我的问题更多......为什么你会想要使用伊娃时期 - 经验丰富与否。使用ivar的性能差异真的很合理吗?



另外作为澄清点,我根据需要覆盖了setter和getter并使用与getter / setter内部属性相关的ivar。但是,在getter / setter或init之外,我总是使用 self.myProperty 语法。






编辑1



我感谢所有好的回复。我想解决的一个看起来不正确的是,使用ivar,你可以获得封装,而不是你拥有的属性。只需在类连续中定义属性即可。这会将财产与外人隐藏起来。您还可以在接口中声明属性readonly并在实现中将其重新定义为readwrite,如:

  //只读外部人
@property(nonatomic,copy,readonly)NSString * name;

并且在课程续集中:

  //在此文件中读写
@property(非原子,复制)NSString * name;

要让它完全私有,只能在课程续集中声明它。

解决方案

封装



如果ivar是私有的,程序的其他部分不能轻松搞定。通过声明的属性,聪明的人可以通过访问者轻松访问和变异。



性能



是,这在某些情况下会有所不同。有些程序有限制,他们不能在程序的某些部分使用任何objc消息(想想实时)。在其他情况下,您可能希望直接访问它以获得速度。在其他情况下,这是因为objc消息传递充当优化防火墙。最后,它可以减少您的引用计数操作并最小化峰值内存使用(如果正确完成)。



非平凡类型



<例子:如果您有C ++类型,有时候直接访问就是更好的方法。该类型可能无法复制,或者复制可能并不简单。



多线程



你的许多人ivars是相互依赖的。您必须确保多线程上下文中的数据完整性。因此,您可能倾向于直接访问关键部分中的多个成员。如果您坚持使用访问器来获取相关数据,那么您的锁通常必须是可重入的,并且您通常最终会进行更多的收购(有时会更多)。



程序正确性



由于子类可以覆盖任何方法,因此最终可能会发现写入接口与正确管理状态之间存在语义差异。程序正确性的直接访问在部分构造的状态中尤为常见 - 在初始化程序和 dealloc 中,最好使用直接访问。你也可以在访问器,便利构造函数, copy mutableCopy 的实现中找到这种常见的,并且归档/序列化实现。



当从所有具有公共读写访问器思维模式转移到隐藏其实现细节/数据的思维模式时,它也更频繁好。有时您需要正确地绕过子类'覆盖可能引入的副作用才能做正确的事。



二进制大小



默认情况下声明所有读写操作通常会导致许多访问器方法,当您考虑程序执行一会儿时,这些方法永远不需要。所以它会给你的程序和加载时间增加一些脂肪。



最小化复杂度



在某些情况下,完全没必要添加+ type +为一个简单的变量维护所有额外的脚手架,例如用一个方法编写并在另一个方法中读取的私有bool。






完全没有说使用属性或访问器是不好的 - 每个都有重要的好处和限制。与许多OO语言和设计方法一样,您也应该支持在ObjC中具有适当可见性的访问者。有时你需要偏离。出于这个原因,我认为通常最好限制对声明ivar的实现的直接访问(例如声明它 @private )。






re编辑1:



我们大多数人都记得如何动态调用隐藏的访问器(只要我们知道名称......)。与此同时,我们大多数人都没有没有记住如何正确访问不可见的ivars(超出KVC)。类继续帮助,但它确实引入了漏洞。



这种解决方法很明显:

  if([obj respondsToSelector:(@ selector(setName :)])
[(id)obj setName:@Al Paca];

现在只用ivar尝试,没有KVC。


I usually see this question asked the other way, such as Must every ivar be a property? (and I like bbum's answer to this Q).

I use properties almost exclusively in my code. Every so often, however, I work with a contractor who has been developing on iOS for a long time and is a traditional game programmer. He writes code that declares almost no properties whatsoever and leans on ivars. I assume he does this because 1.) he's used to it since properties didn't always exist until Objective C 2.0 (Oct '07) and 2.) for the minimal performance gain of not going through a getter / setter.

While he writes code that doesn't leak, I'd still prefer him to use properties over ivars. We talked about it and he more or less sees not reason to use properties since we weren't using KVO and he's experienced with taking care of the memory issues.

My question is more... Why would you ever want to use an ivar period - experienced or not. Is there really that great of a performance difference that using an ivar would be justified?

Also as a point of clarification, I override setters and getters as needed and use the ivar that correlates with that property inside of the getter / setter. However, outside of a getter / setter or init, I always use the self.myProperty syntax.


Edit 1

I appreciate all of the good responses. One that I'd like to address that seems incorrect is that with an ivar you get encapsulation where with a property you don't. Just define the property in a class continuation. This will hide the property from outsiders. You can also declare the property readonly in the interface and redefine it as readwrite in the implementation like:

// readonly for outsiders
@property (nonatomic, copy, readonly) NSString * name;

and have in the class continuation:

// readwrite within this file
@property (nonatomic, copy) NSString * name;

To have it completely "private" only declare it in the class continuation.

解决方案

Encapsulation

If the ivar is private, the other parts of the program can't get at it as easily. With a declared property, the clever people can access and mutate quite easily via the accessors.

Performance

Yes, this can make a difference in some cases. Some programs have constraints where they can not use any objc messaging in certain parts of the program (think realtime). In other cases, you may want to access it directly for speed. In other cases, it's because objc messaging acts as an optimization firewall. Finally, it can reduce your reference count operations and minimize peak memory usage (if done correctly).

Nontrivial Types

Example: If you have a C++ type, direct access is just the better approach sometimes. The type may not be copyable, or it may not be trivial to copy.

Multithreading

Many of your ivars are codependent. You must ensure your data integrity in multithreaded context. Thus, you may favor direct access to multiple members in critical sections. If you stick with accessors for codependent data, your locks must typically be reentrant and you will often end up making many more acquisitions (significantly more at times).

Program Correctness

Since the subclasses can override any method, you may eventually see there is a semantic difference between writing to the interface versus managing your state appropriately. Direct access for program correctness is especially common in partially constructed states -- in your initializers and in dealloc, it's best to use direct access. You may also find this common in the implementations of an accessor, a convenience constructor, copy, mutableCopy, and archiving/serialization implementations.

It's also more frequent as one moves from the everything has a public readwrite accessor mindset to one which hides its implementation details/data well. Sometimes you need to correctly step around side effects a subclass' override may introduce in order to do the right thing.

Binary Size

Declaring everything readwrite by default usually results in many accessor methods you never need, when you consider your program's execution for a moment. So it will add some fat to your program and load times as well.

Minimizes Complexity

In some cases, it's just completely unnecessary to add+type+maintain all that extra scaffolding for a simple variable such as a private bool that is written in one method and read in another.


That's not at all to say using properties or accessors is bad - each has important benefits and restrictions. Like many OO languages and approaches to design, you should also favor accessors with appropriate visibility in ObjC. There will be times you need to deviate. For that reason, I think it's often best to restrict direct accesses to the implementation which declares the ivar (e.g. declare it @private).


re Edit 1:

Most of us have memorized how to call a hidden accessor dynamically (as long as we know the name…). Meanwhile, most of us have not memorized how to properly access ivars which aren't visible (beyond KVC). The class continuation helps, but it does introduce vulnerabilities.

This workaround's obvious:

if ([obj respondsToSelector:(@selector(setName:)])
  [(id)obj setName:@"Al Paca"];

Now try it with an ivar only, and without KVC.

这篇关于你为什么要用伊娃?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆