2010-07-22 13 views
9

Si un BOOL tiene un bonito nombre corto, que es bastante fácil de escribir:Cacao - alternar un BOOL sin repetir su nombre

myBOOL = !myBOOL; 

Pero ¿y si la BOOL tiene un nombre largo?

objectWithLongishName.memberWithLongishName.submember.myBOOL = !(objectWithLongishName.memberWithLongishName.submember.myBOOL); 

. . . no se ve tan bonito

Me pregunto si hay una manera fácil de alternar el BOOL sin ingresar su nombre dos veces?

+0

Simplemente curioso, ¿puedes multiplicar un 'bool' por un numérico en Objective-C? ¿Podría hacer algo así como 'objectWithLongishName.memberWithLongishName.submember.myBOOL * = - 1;'? Parece que sería una forma muy * muy * mala de hacerlo, pero ahora me pregunto si funcionaría ... – FrustratedWithFormsDesigner

+0

@frust: Aparte de otras cuestiones, ¿cómo funcionaría eso aritméticamente? '0 * -1 = 0'. –

+0

@Georg Fritzsche: jajaja! Ok, buen punto. Pensé que había visto ese truco * algún * donde, pero no recuerdo dónde (aunque sé que no era Objective-C). – FrustratedWithFormsDesigner

Respuesta

10

Aquí hay otro:

MyBooleanYaddaYadda ^= YES; 

Esto es algo frágil: se romperá en el código C heredado que implica que cualquier entero distinto de cero se evalúa como verdadero. Pero, de nuevo, también lo hará el código del marco de Apple: encontré casos en Cocoa donde un int no distinto de cero, cuando pasaba como BOOL, no causaba el mismo efecto que pasar un SÍ.

Sin embargo, no se basa en el patrón de bits de SÍ, solo en NO es 0. Lo cual es casi un hecho, considerando la forma en que C interpreta los enteros como valores lógicos. Además, no asume el tipo de datos real de BOOL (que en Cocoa es signed char, por cierto).

El patrón de bits de YES en Cocoa es 1. Pero esa no es una convención universal. En algunas plataformas sin tipo de datos booleanos incorporados, la constante entera que sirve como TRUE lógico es -1 - todos los bits. Eso es 0xFFFFFFFF si se interpreta como sin signo. Esta codificación tiene una vaga ventaja de que bitwize NOT (el operador ~ en C) es equivalente a NOT lógico (el operador! En C). Es decir, ~ 0xFFFFFFFF es 0, i. mi. ~ TRUE es FALSO. No funciona de esa manera si TRUE se define como 1.

+1

Esto falla un punto de claridad de código. A simple vista, parece una asignación a SÍ. Úselo mucho, y el idioma probablemente se destacará, pero toque fresco, probablemente le cause un poco de rasguño en la cabeza. –

+0

IMO la brevedad y la falta de infraestructura asociada requerida (es decir, definiciones macro) superan esta desventaja. Es por eso que acepté esta respuesta. A cada cual, lo suyo. –

9

No hay una manera obvia en (Objective-) C de hacer lo que usted describe (sin usar un macro de preprocesador), pero vea la respuesta de Seva para una posible solución (aunque potencialmente frágil). Más importante aún, algo como objectWithLongishName.memberWithLongishName.submember.myBOOL indica una violación Law of Demeter; Debería proporcionar submember directamente a cualquier unidad de código que necesite acceder al submember.myBOOL.

+0

¿Por qué aBool^= YES no es viable? – Kalle

+0

@Kalle, buen punto. Creo que @Seva Alekseyev hace el punto bastante claro. Usar '^ =' es potencialmente frágil, pero funcionará en muchas situaciones. –

6

Escriba un método para la clase submember que lo cambia por usted?

- (void) toggleMyBOOL { 
    self.myBool = !self.myBool; 
} 

A continuación, puede hacer:

[objectWithLongishName.memberWithLongishName.submember toggleMyBOOL]; 
10
#define NOT(b) (b) = !(b) 

NOT(MyBooleanVariableWithAFreakishlyLongName); 

O, si se trata de Objective C++:

inline void NOT(BOOL &b) 
{ 
    b = !b; 
} 
+3

Habría llamado la macro al TOGGLE, pero lo que sea que lo haga por ti ... – FrustratedWithFormsDesigner

+0

Ese fue mi primer borrador :) –

2

Use XOR. En C, esto es ^.

BOOL x = YES; 
x ^= YES; // it's now NO 
x ^= YES; // it's now YES 
x ^= YES; // it's now NO 
x ^= YES; // it's now YES 
x ^= YES; // it's now NO 
x ^= YES; // it's now YES 
... 

Editar: Alguien ha publicado esto, aparentemente. Creo que debería decir que nunca he usado esto en el código. :-)

+1

Tenga en cuenta que se trata de un XOR bitwise, lo que significa que si 'x' es, por algún motivo, establecido en cualquier valor que no sea 1 o 0, siempre seguirá siendo cierto, ya que solo está volteando el bit más bajo. Usar '~ NO' reemplazará ese problema con otro: Va a voltear * todos * los bits, con el mismo resultado:' x' simplemente alterna entre dos valores verdaderos. –

+0

Y * es por eso que lo publiqué como un comentario y dije "... pero no lo haría". ;) Sin embargo, está claro que está "bien". – Wevah

+0

Si logra obtener un BOOL igual a un valor distinto de 1 o 0, entonces sí, tendrá problemas. Pero no lo harás, sin importar? – Kalle

0

Tiene un conjunto precioso de respuestas centradas en cambiar un SÍ a un NO o viceversa, pero no responde que tocó lo que podría parecer un problema arquitectónico en el código.

Bueno, algunas respuestas. Estoy ciego.

Es decir, que tienen la siguiente:

objectWithLongishName.memberWithLongishName.submember.myBOOL = 
    !(objectWithLongishName.memberWithLongishName.submember.myBOOL); 

que huele a una posible violación de encapsulación. En particular (y suponiendo que se trata de una capa de modelo), significa que la conectividad del subgrupo de objetos se expone abiertamente, se aplana, de manera efectiva, el punto de entrada de esa ruta; cualquiera que sea objectWithLongishName, ahora debe tener un conocimiento más bien íntimo de las entrañas de los objetos a lo largo del resto del camino.

Normalmente, no se profundiza en la capa de modelo a lo largo de las rutas clave para editar el estado fuera de la capa de enlaces de cacao (e incluso eso es un poco frágil).

A veces, estos caminos largos tienen sentido. En tal caso, dejaría la forma über-verbose que tiene arriba como una indicación visual de que la encapsulación se destruye a propósito.

+1

@Barry Wark mencionó esto (La violación de la Ley de Demeter) –

+0

Actual, la * primera * (o una de las primeras) respuestas (respuesta de Barry Wark) mencionó eso. – FrustratedWithFormsDesigner

Cuestiones relacionadas