как работает подчеркивание перед переменной в классе target-c какао?

<p>я видел в нескольких примерах iphone, что атрибуты используют подчеркивание \_ перед переменной. кто-нибудь знает что это значит? или как это работает?</p><p>файл интерфейса, который я использую, выглядит следующим образом:</p><pre><code>@interface missioncell : uitableviewcell { mission *\_mission; uilabel *\_missionname; } @property (nonatomic, retain) uilabel *missionname; - (mission *)mission; </code></pre><p>я не уверен точно, что делает вышеупомянутое, но когда я пытаюсь установить название миссии как:</p><pre><code>amission.missionname = missionname; </code></pre><p>я получаю ошибку:</p><blockquote> <p>запрос на членство 'missionname' в чем-то, не являющемся структурой или объединением</p> </blockquote>

<p>если вы используете префикс подчеркивания для своих ivars (который является не чем иным, как обычным соглашением, но полезным), то вам нужно сделать 1 дополнительную вещь, чтобы автоматически сгенерированный аксессор (для свойства) знал, какой ivar использовать. в частности, в вашем файле реализации ваше <code>synthesize</code> должно выглядеть так:</p><pre><code>@synthesize missionname = \_missionname; </code></pre><p>в более общем смысле это:</p><pre><code>@synthesize propertyname = \_ivarname; </code></pre>

<p>это просто соглашение по удобочитаемости, оно не делает ничего особенного для компилятора. вы увидите, как люди используют его для личных переменных экземпляра и имен методов. apple на самом деле рекомендует не использовать подчеркивание (если вы не будете осторожны, вы можете переопределить что-то в своем суперклассе), но вы не должны расстраиваться из-за игнорирования этого совета. :)</p>

<p>единственная полезная цель, которую я видел, состоит в том, чтобы различать локальные переменные и переменные-члены, как указано выше, но это не является необходимым соглашением. в паре с @property это увеличивает многословность синтезирующих операторов - <code>@synthesize missionname = \_missionname;</code>, и везде безобразно.</p><p>вместо использования подчеркивания, просто используйте описательные имена переменных внутри методов, которые не конфликтуют. когда они должны конфликтовать, <strong>имя переменной в методе должно иметь подчеркивание, а не переменную-член, которая может использоваться несколькими методами</strong>. единственное общее место, где это полезно, это метод set или метод init. кроме того, это сделает оператор @synthesize более кратким.</p><pre><code>-(void)setmystring:(nsstring*)\_mystring { mystring = \_mystring; } </code></pre><p><strong>edit:</strong> благодаря последней функции компилятора автоматического синтеза я теперь использую подчеркивание для ivar (в редких случаях, когда мне нужно использовать ivar для соответствия функциям автоматического синтеза.</p>

<p>на самом деле это ничего не значит, это просто соглашение, которое некоторые люди используют для дифференциации переменных-членов от локальных переменных.</p><p>что касается ошибки, похоже, что amission имеет неправильный тип. каково это его объявление?</p>

<p>это только для соглашения об именовании свойств синтеза.</p><p>когда вы синтезируете переменные в файле .m, xcode автоматически предоставит вам \_variable интеллект.</p>

<p>наличие подчеркивания не только позволяет разрешать ваши ивары, не прибегая к использованию синтаксиса <em>self.member</em>, но и делает ваш код более читабельным, поскольку вы знаете, когда переменная является иваром (из-за префикса подчеркивания) или аргумент члена (без подчеркивания).</p><p>пример:</p><pre><code>- (void) displayimage: (uiimage *) image { if (image != nil) { // display the passed image... [\_imageview setimage: image]; } else { // fall back on the default image... [\_imageview setimage: \_image]; } } </code></pre>

<p>похоже, что это "главный" пункт для вопросов о self.variablename и \_variablename. что бросило меня в тупик, так это то, что в .h у меня было:</p><pre><code>... @interface myclass : parentclass { classname *variablename; // note lack of \_ } @property (strong, nonatomic) classname *variablename; ... </code></pre><p>это приводит к тому, что self.variablename и \_variablename являются двумя различными переменными в .m. что мне нужно было:</p><pre><code>... @interface myclass : parentclass { classname *\_variablename; // note presence of \_ } @property (strong, nonatomic) classname *variablename; ... </code></pre><p>затем в классе '.m self.variablename и \_variablename эквивалентны.</p><p>что я до сих пор не понимаю, так это то, почему многие примеры все еще работают, даже если это не сделано.</p><p>луч</p>

<p>из других ответов отсутствует то, что использование <code>\_variable</code> не позволяет вам бездумно набирать <code>variable</code> и получать доступ к ivar, а не к (предположительно предполагаемому) свойству.</p><p>компилятор заставит вас использовать <code>self.variable</code> или <code>\_variable</code>. использование подчеркивания делает невозможным ввод <code>variable</code>, что уменьшает ошибки программиста.</p><pre><code>- (void)foomethod { // error - "use of undeclared identifier 'foo', did you mean '\_foo'?" foo = @1; // so instead you must specifically choose to use the property or the ivar: // property self.foo = @1; // ivar \_foo = @1; } </code></pre>

<p>вместо подчеркивания вы можете использовать имя self.variable или вы можете синтезировать переменную, чтобы использовать переменную или выход без подчеркивания.</p>