¿Cuál es la diferencia entre los métodos de clase e instancia?

448

¿Cuál es la diferencia entre un método de clase y un método de instancia?

¿Los métodos de instancia son los accesores (getters y setters) mientras que los métodos de clase son prácticamente todo lo demás?

Devoto
fuente

Respuestas:

673

Como la mayoría de las otras respuestas han dicho, los métodos de instancia usan una instancia de una clase, mientras que un método de clase se puede usar solo con el nombre de la clase. En Objective-C se definen así:

@interface MyClass : NSObject

+ (void)aClassMethod;
- (void)anInstanceMethod;

@end

Entonces podrían usarse así:

[MyClass aClassMethod];

MyClass *object = [[MyClass alloc] init];
[object anInstanceMethod];

Algunos ejemplos del mundo real de los métodos de clase son los métodos de conveniencia en muchas clases de Foundation como NSString's +stringWithFormat:o NSArray' s +arrayWithArray:. Un método de instancia sería NSArrayel -countmétodo de.

Cory Kilger
fuente
77
Buena respuesta. También vale la pena señalar que verá una notación abreviada particular para describir los métodos. Por ejemplo, + [NSString stringWithFormat:] es el método de clase + stringWithFormat: en NSString; - [NSArray objectAtIndex:] es un método de instancia. Los métodos con varias partes del selector se escriben como: [NSMutableDictionary setObject: forKey:] etc. A menudo verá esta notación en las respuestas de Cocoa, la documentación y en Xcode.
Quinn Taylor
149
Yo agregaría que un método de clase se llama método "estático" en muchos otros idiomas. Y para responder a la pregunta original, los accesores son métodos de instancia porque establecen y obtienen el estado de una instancia específica. En el ejemplo anterior, el recuento de NSArray devuelve el número de objetos en una instancia específica.
Brian Pan
2
"mientras que un método de clase se puede usar solo con el nombre de la clase". o el objeto de clase
user102008
2
Perdón por mi entusiasmo ... pero acabo de aprender la diferencia y su potencial. ¡los métodos de clase son geniales y también las clases singleton! ufff me he enamorado! <3
Pavan
2
Los métodos estáticos y de clase de @BrianPan no son lo mismo. Son similares, pero la razón por la que se nombran de manera diferente es porque funcionan de manera diferente. Por ejemplo, los métodos estáticos no se pueden anular.
Sulthan
190

Todos los detalles técnicos se han cubierto muy bien en las otras respuestas. Solo quiero compartir una analogía simple que creo que ilustra muy bien la diferencia entre una clase y una instancia:

ingrese la descripción de la imagen aquí

Una clase es como el plano de una casa: solo tienes un plano y (generalmente) no puedes hacer tanto con el plano solo.

ingrese la descripción de la imagen aquí

Una instancia (o un objeto ) es la casa real que construyes según el plano: puedes construir muchas casas a partir del mismo plano. Luego, puede pintar las paredes de un color diferente en cada una de las casas, así como puede cambiar de forma independiente las propiedades de cada instancia de una clase sin afectar las otras instancias.

Johannes Fahrenkrug
fuente
66
@JohannesFahrenkrug Bien explicó el concepto de clase y objeto aquí. No es la pregunta real para difference between class method and an instance method ;
Shekhu
1
Explicación perfecta de Clase vs Instancia de una clase. Las clases son un concepto extraño para los novatos y esto lo explica en su forma más fundamental.
Alex McPherson el
1
@JohannesFahrenkrug realmente una buena explicación, lo que me hizo pensar cómo ambos difieren y cuándo usar ambos
ChenSmile
1
Una gran explicación :)
Praveenkumar
1
Buena analogia Por favor, que alguien le de a este tipo un año de pizzas.
GeneCode
102

Como han dicho las otras respuestas, los métodos de instancia operan en un objeto y tienen acceso a sus variables de instancia, mientras que un método de clase opera en una clase como un todo y no tiene acceso a las variables de una instancia en particular (a menos que pase la instancia como parámetro).

Un buen ejemplo de un método de clase es un método de tipo contador, que devuelve el número total de instancias de una clase. Los métodos de clase comienzan con a +, mientras que los de instancia comienzan con un -. Por ejemplo:

static int numberOfPeople = 0;

@interface MNPerson : NSObject {
     int age;  //instance variable
}

+ (int)population; //class method. Returns how many people have been made.
- (id)init; //instance. Constructs object, increments numberOfPeople by one.
- (int)age; //instance. returns the person age
@end

@implementation MNPerson
- (id)init{
    if (self = [super init]){
          numberOfPeople++;
          age = 0;
    }    
    return self;
}

+ (int)population{ 
     return numberOfPeople;
}

- (int)age{
     return age;
}

@end

main.m:

MNPerson *micmoo = [[MNPerson alloc] init];
MNPerson *jon = [[MNPerson alloc] init];
NSLog(@"Age: %d",[micmoo age]);
NSLog(@"%Number Of people: %d",[MNPerson population]);

Salida: Edad: 0 Número de personas: 2

Otro ejemplo es si tiene un método al que desea que el usuario pueda llamar, a veces es bueno hacerlo un método de clase. Por ejemplo, si tiene una clase llamada MathFunctions, puede hacer esto:

+ (int)square:(int)num{ 
      return num * num;
}

Entonces el usuario llamaría:

[MathFunctions square:34];

sin tener que instanciar la clase!

También puede usar funciones de clase para devolver objetos lanzados automáticamente, como los de NSArray

+ (NSArray *)arrayWithObject:(id)object

Eso toma un objeto, lo coloca en una matriz y devuelve una versión de la matriz que se ha publicado automáticamente y que no tiene que ser administrada en memoria, ideal para matrices temperorarias y otras cosas.

¡Espero que ahora entiendas cuándo y / o por qué deberías usar métodos de clase!

micmoo
fuente
1
micmoo, ¿puedo sugerirle que ponga el "static int numberOfPeople = 0;" en texto con formato de código? Estaba confundido hasta que me di cuenta por encima del código de muestra. Aparte de eso, una respuesta muy concisa.
mobibob
2
Disculpe la confusión de mi novato, pero ¿por qué necesita tanto la variable de instancia "age" como el método de instancia "age"? ¿No se crearán getter y setter, por ejemplo, la variable "age" con @synthetize?
selytch
@selytch "age" debería definirse como una propiedad para poder utilizar sintetizar.
micah94
36

Un método de instancia se aplica a una instancia de la clase (es decir, un objeto) mientras que un método de clase se aplica a la clase misma.

En C #, un método de clase está marcado como estático. Los métodos y propiedades no marcados como estáticos son métodos de instancia.

class Foo {
  public static void ClassMethod() { ... }
  public void InstanceMethod() { ... }
}
Robert Horvick
fuente
1
Argh: lo siento, me acabo de dar cuenta de que esta es una pregunta de Obj-C. Espero que mi respuesta todavía se aplique, pero vote hacia abajo o vote para eliminar.
Robert Horvick
66
Ningún daño hecho. La primera parte de su respuesta es correcta como principio general de OOP, y definitivamente se aplica a Objective-C. Puede agregar "Objective-C" a su lista de etiquetas para ignorarlas si no desea ver esas preguntas, aunque cualquier participación es ciertamente bienvenida. :-)
Quinn Taylor
16

La respuesta a su pregunta no es específica del objetivo c, sin embargo, en diferentes lenguajes, los métodos de clase pueden llamarse métodos estáticos.

La diferencia entre los métodos de clase y los métodos de instancia son

Métodos de clase

  • Operar en variables de clase (no pueden acceder a variables de instancia)
  • No requiere que un objeto sea instanciado para ser aplicado
  • A veces puede ser un olor a código (algunas personas que son nuevas en OOP usan como muleta para hacer Programación Estructurada en un entorno OO)

Métodos de instancia

  • Operar en variables de instancias y variables de clase
  • Debe tener un objeto instanciado para operar
hhafez
fuente
Los métodos de instancia pueden operar en variables de clase?
蘇健豪
16

Creo que la mejor manera de entender esto es mirar allocy init. Fue esta explicación la que me permitió comprender las diferencias.

Método de clase

Se aplica un método de clase a la clase como un todo. Si marca el allocmétodo, ese es un método de clase denotado por +antes de la declaración del método. Es un método de clase porque se aplica a la clase para hacer una instancia específica de esa clase.

Método de instancia

Utiliza un método de instancia para modificar una instancia específica de una clase que es exclusiva de esa instancia, en lugar de la clase en su conjunto. initpor ejemplo (indicado con un -antes de la declaración del método), es un método de instancia porque normalmente está modificando las propiedades de esa clase después de que se haya creado con alloc.

Ejemplo

NSString *myString = [NSString alloc];

Está llamando al método de clase allocpara generar una instancia de esa clase. Observe cómo el receptor del mensaje es una clase.

[myString initWithFormat:@"Hope this answer helps someone"];

Está modificando la instancia de NSStringinvocado myStringal establecer algunas propiedades en esa instancia. Observe cómo el receptor del mensaje es una instancia (objeto de clase NSString).

Adam Waite
fuente
¿Qué quiere decir con marcar el método "alloc"? ¿Me puede indicar un lugar específico en la documentación? (editar) -> ahh no importa, sí, en los documentos de NSObject dice que en "Tareas" - developer.apple.com/library/ios/documentation/cocoa/reference/…
Ethan Parker
Realmente no necesitas entender lo que realmente hace para comprender esto, solo que se aplica a la clase. En pocas palabras: allocasigna suficiente memoria para el objeto, initmodificará lo que hay en esas direcciones de memoria para definir el estado del objeto. No podemos modificar un objeto a menos que haya un espacio para modificarlo, así que lo usamos allocen la clase que decidirá darnos ese espacio.
Adam Waite
6

Los métodos de clase generalmente se usan para crear instancias de esa clase

Por ejemplo, [NSString stringWithFormat:@"SomeParameter"];devuelve una NSStringinstancia con el parámetro que se le envía. Por lo tanto, debido a que es un método de Clase que devuelve un objeto de su tipo, también se llama un método de conveniencia.

iosrookie
fuente
6

Entonces si lo entiendo correctamente.

Un classmétodo no necesita que asigne una instancia de ese objeto para usarlo / procesarlo. Un classmétodo es autónomo y puede funcionar sin ninguna dependencia del estado de ningún objeto de esa clase. Se classespera que un método asigne memoria para todo su propio trabajo y desasigne cuando haya terminado, ya que ninguna instancia de esa clase podrá liberar memoria asignada en llamadas anteriores al método de clase.

Un instancemétodo es todo lo contrario. No puede llamarlo a menos que asigne una instancia de esa clase. Es como una clase normal que tiene un constructor y puede tener un destructor (que limpia toda la memoria asignada).

En la mayoría de las probabilidades (a menos que esté escribiendo una biblioteca reutilizable, no debería necesitar una classvariable.

Siddharth
fuente
1
Un caso obvio en el que necesita métodos de clase es la creación de instancias. Debe poder crear instancias sin tener instancias todavía, de lo contrario, la primera instancia nunca podría crearse. Es por eso que + alloc es y debe ser un método de clase.
gnasher729
4

Los métodos de instancias operan en instancias de clases (es decir, "objetos"). Los métodos de clase están asociados con las clases (la mayoría de los idiomas usan la palabra clave staticpara estos tipos).

eduffy
fuente
3

Tomemos, por ejemplo, un juego donde se generan muchos autos ... cada uno pertenece a la clase CCar. Cuando se crea una instancia de un automóvil, hace una llamada a

[CCar registerCar:self]

Entonces, la clase CCar puede hacer una lista de cada CCar instanciado. Digamos que el usuario finaliza un nivel y quiere eliminar todos los autos ... usted podría: 1- Ir a través de una lista de cada CCar que creó manualmente, y hacer whicheverCar.remove(); o 2- Agregar un método removeAllCars a CCar, lo que hará eso para ti cuando llamas a [CCar removeAllCars]. Es decir allCars[n].remove();

O, por ejemplo, permite que el usuario especifique un tamaño de fuente predeterminado para toda la aplicación, que se carga y guarda al inicio. Sin el método de clase, es posible que tenga que hacer algo como

fontSize = thisMenu.getParent().fontHandler.getDefaultFontSize();

Con el método de clase, podría salirse con la suya [FontHandler getDefaultFontSize].

En cuanto a su función removeVowels, encontrará que lenguajes como C # realmente tienen ambos con ciertos métodos como toLower o toUpper.

por ejemplo myString.removeVowels() y String.removeVowels(myString) (en ObjC que sería [String removeVowels:myString]).

En este caso, la instancia probablemente llama al método de clase, por lo que ambos están disponibles. es decir

public function toLower():String{
  return String.toLower();
}

public static function toLower( String inString):String{
 //do stuff to string..
 return newString;
}

básicamente, myString.toLower() llamadas [String toLower:ownValue]

No hay una respuesta definitiva, pero si desea introducir un método de clase mejoraría su código, pruébelo y tenga en cuenta que un método de clase solo le permitirá usar otros métodos / variables de clase.

sicklebrick
fuente
3

métodos de clase

son métodos que se declaran como estáticos. Se puede llamar al método sin crear una instancia de la clase. Los métodos de clase solo pueden funcionar en los miembros de la clase y no en los miembros de la instancia, ya que los métodos de clase desconocen a los miembros de la instancia. Los métodos de instancia de la clase tampoco se pueden invocar desde un método de clase a menos que se invoquen en una instancia de esa clase.

Métodos de instancia

por otro lado, requiere que exista una instancia de la clase antes de que se pueda llamar, por lo que se debe crear una instancia de una clase utilizando la nueva palabra clave. Los métodos de instancia operan en instancias específicas de clases. Los métodos de instancia no se declaran como estáticos.

iCrazyDev
fuente
También se puede crear con la palabra clave "alloc", no solo la "nueva". Además, Objective-C no exige que exista una instancia para llamar a un método de instancia, puede enviar mensajes a un puntero nulo.
Elviss Strazdins
3

En Objective-C, todos los métodos comienzan con un carácter "-" o "+". Ejemplo:

@interface MyClass : NSObject
// instance method
- (void) instanceMethod;

+ (void) classMethod;
@end

Los caracteres "+" y "-" especifican si un método es un class methodo un instance methodrespectivamente.

La diferencia sería clara si llamamos a estos métodos. Aquí se declaran los métodos en MyClass.

instance method requiere una instancia de la clase:

MyClass* myClass = [[MyClass alloc] init];
[myClass instanceMethod];

Dentro de MyClassotros métodos se pueden llamar métodos de instancia de MyClassuso self:

-(void) someMethod
{
    [self instanceMethod];
}

Pero, class methodsdebe llamarse a la clase en sí:

[MyClass classMethod];

O:

MyClass* myClass = [[MyClass alloc] init];
[myClass class] classMethod];

Esto no funcionará:

// Error
[myClass classMethod];
// Error
[self classMethod];
Tulon
fuente
3

MÉTODOS DE CLASE


Un método de clase generalmente crea una nueva instancia de la clase o recupera algunas propiedades globales de la clase. Los métodos de clase no funcionan en una instancia ni tienen acceso a la variable de instancia.


MÉTODOS DE INSTANCIA


Un método de instancia opera en una instancia particular de la clase. Por ejemplo, el método de acceso que implementó son todos métodos de instancia. Los usa para establecer u obtener las variables de instancia de un objeto en particular.


INVOCAR


Para invocar un método de instancia, envía el mensaje a una instancia de la clase.

Para invocar un método de clase, envía el mensaje a la clase directamente.


Fuente: IOS - Objective-C - Métodos de clase y métodos de instancia

Nam N. HUYNH
fuente
1

Los métodos de clase no pueden cambiar ni conocer el valor de ninguna variable de instancia. Ese debería ser el criterio para saber si un método de instancia puede ser un método de clase.

Deepee
fuente
-1 de mí, porque puede pasar la instancia al método de clase y podrá cambiar y conocer los valores de sus variables.
Elviss Strazdins
1

También recuerde, la misma idea se aplica a las variables. Encontrará términos como estático, miembro, instancia, clase, etc. cuando hable de variables de la misma manera que lo haría para métodos / funciones.

Parece que el término común en la comunidad Obj-C es ivar por ejemplo variable, pero todavía no soy un tipo Obj-C.

Medio duplex
fuente
1

Una actualización de las respuestas anteriores, estoy de acuerdo en que los métodos de instancia usan una instancia de una clase, mientras que un método de clase se puede usar solo con el nombre de la clase.

Ya no hay ninguna diferencia entre el método de instancia y el método de clase después de que el conteo automático de referencias surgió en Objective-C.

Por ejemplo, [NS StringWithformat:..]un método de clase y [[NSString alloc] initwihtformat:..]un método de instancia, ambos son iguales después de ARC

usuario1292809
fuente
1

Nota: Esto solo está en formato de pseudocódigo

Método de clase

Casi todo lo que necesita hacer es durante el tiempo de compilación . No necesita ninguna entrada del usuario, ni su cálculo se basa en una instancia. Todo se basa en la clase / plano, que es único, es decir, no tiene múltiples planos para una clase. ¿Puedes tener diferentes variaciones durante el tiempo de compilación? No, por lo tanto, la clase es única, por lo que no importa cuántas veces llame a un método de clase, el puntero que apunta a él sería el mismo.

PlanetOfLiving: return @"Earth" // No matter how many times you run this method...nothing changes.

Método de instancia

Por el contrario, el método de instancia ocurre durante el tiempo de ejecución, ya que es solo entonces que ha creado una instancia de algo que podría variar en cada instanciación.

initWithName: @"John" lastName: @"Doe"Age:12 @"cool"
initWithName: @"Donald" lastName: @"Drumpf"Age:5 attitude:@"He started"
initWithName: @"President" lastName: @"Obama"Age:54 attitude: @"Awesome"
//As you can see the value can change for each instance.

Si viene de otros idiomas, los métodos estáticos son los mismos que los métodos de clase.
Si viene de Swift, los métodos de tipo son los mismos que los métodos de clase.

Miel
fuente
0

Agregando a las respuestas anteriores

El método de clase funcionará en la clase, lo usaremos para fines generales donde como + stringWithFormat, tamaño de clase y lo más importante para init, etc.

NSString *str = [NSString stringWithFormat:@"%.02f%%",someFloat]; 

El método de instancia funcionará en una instancia de una clase, no en una clase como si tuviéramos dos personas y queremos conocer el balance de cada una por separado. Necesitamos usar el método de instancia. Porque no devolverá una respuesta general. por ejemplo, como determinar el recuento de NSSArray, etc.

[johnson getAccountBalance];
[ankit getAccountBalance];
Ankit Garg
fuente