Qual é a diferença entre os métodos de classe e instância?

448

Qual é a diferença entre um método de classe e um método de instância?

Os métodos de instância são os acessadores (getters e setters), enquanto os métodos de classe são praticamente tudo o resto?

Dedicado
fonte

Respostas:

673

Como a maioria das outras respostas já disse, os métodos de instância usam uma instância de uma classe, enquanto um método de classe pode ser usado apenas com o nome da classe. No Objetivo-C, eles são definidos assim:

@interface MyClass : NSObject

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

@end

Eles poderiam ser usados ​​assim:

[MyClass aClassMethod];

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

Alguns exemplos reais de métodos de classe são os métodos de conveniência em muitas classes do Foundation, como NSString's ' +stringWithFormat:ou NSArray's +arrayWithArray:. Um método de instância seria NSArrayo -countmétodo de.

Cory Kilger
fonte
7
Boa resposta. Também é importante notar que você verá uma notação abreviada em particular para descrever métodos. Por exemplo, + [NSString stringWithFormat:] é o método de classe + stringWithFormat: on NSString; - [NSArray objectAtIndex:] é um método de instância. Métodos com várias partes do seletor são escritos como - [NSMutableDictionary setObject: forKey:] etc. Você frequentemente verá essa notação nas respostas do Cocoa, na documentação e no Xcode.
Quinn Taylor
149
Eu acrescentaria que um método de classe é chamado de método "estático" em muitos outros idiomas. E para responder à pergunta original, os acessadores são métodos de instância porque estão definindo e obtendo o estado de uma instância específica. No exemplo acima, o NSArray count retorna o número de objetos em uma instância específica.
Brian Pan
2
"enquanto um método de classe pode ser usado apenas com o nome da classe." ou o objeto de classe
user102008
2
Desculpe pela minha empolgação ... mas eu acabei de aprender a diferença e seu potencial. métodos de classe rock e assim como classes singleton! ufff eu me apaixonei! <3
Pavan
2
Os métodos estáticos e de classe @BrianPan não são os mesmos. Eles são semelhantes, mas o motivo pelo qual são nomeados de maneira diferente é que eles funcionam de maneira diferente. Por exemplo, métodos estáticos não podem ser substituídos.
Sulthan
190

Todos os detalhes técnicos foram bem abordados nas outras respostas. Eu só quero compartilhar uma analogia simples que eu acho que ilustra bem a diferença entre uma classe e uma instância:

insira a descrição da imagem aqui

Uma classe é como a planta de uma casa: você só tem uma planta e (geralmente) não pode fazer muito isso apenas com a planta.

insira a descrição da imagem aqui

Uma instância (ou um objeto ) é a casa real que você constrói com base no blueprint: Você pode construir muitas casas a partir do mesmo blueprint. Em seguida, você pode pintar as paredes com uma cor diferente em cada uma das casas, assim como alterar independentemente as propriedades de cada instância de uma classe sem afetar as outras instâncias.

Johannes Fahrenkrug
fonte
6
@JohannesFahrenkrug Explicou bem o conceito de classe e objeto aqui. Não é a pergunta real difference between class method and an instance method ;
Shekhu 10/07/2015
1
Explicação perfeita de Classe vs Instância de uma classe. As aulas são um conceito estranho para iniciantes e isso explica da maneira mais fundamental.
Alex McPherson
1
@JohannesFahrenkrug realmente uma boa explicação, o que me fez pensar como boths r diff e quando usar os dois
ChenSmile
1
Como uma grande Explicação :)
Praveenkumar
1
Boa analogia. Por favor, alguém dê a esse cara um suprimento de pizzas por ano.
GeneCode 04/07
102

Como as outras respostas disseram, os métodos de instância operam em um objeto e têm acesso a suas variáveis ​​de instância, enquanto um método de classe opera em uma classe como um todo e não tem acesso às variáveis ​​de uma instância específica (a menos que você passe a instância como um parâmetro).

Um bom exemplo de um método de classe é um método do tipo contador, que retorna o número total de instâncias de uma classe. Os métodos de classe começam com a +, enquanto os da instância começam com um -. Por exemplo:

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]);

Saída: Idade: 0 Número de pessoas: 2

Outro exemplo é se você possui um método que deseja que o usuário possa chamar, às vezes é bom torná-lo um método de classe. Por exemplo, se você tiver uma classe chamada MathFunctions, poderá fazer o seguinte:

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

Então o usuário ligaria para:

[MathFunctions square:34];

sem precisar instanciar a classe!

Você também pode usar funções de classe para retornar objetos liberados automaticamente, como o NSArray

+ (NSArray *)arrayWithObject:(id)object

Isso pega um objeto, coloca-o em uma matriz e retorna uma versão liberada automaticamente da matriz que não precisa ser gerenciada por memória, excelente para matrizes temperamentais e outras coisas.

Espero que agora você entenda quando e / ou por que você deve usar métodos de classe!

micmoo
fonte
1
micmoo, sugiro que você coloque o "static int numberOfPeople = 0;" no texto formatado em código? Fiquei confuso até perceber acima do código de exemplo. Fora isso, uma resposta realmente concisa.
Mobibob
2
Perdoe minha confusão de novatos, mas por que você precisa da variável de instância "idade" e do método de instância "idade"? O getter e o setter, por exemplo, a variável "age" não serão criados com @synthetize?
Selytch
@selytch "age" teria que ser definido como uma propriedade para usar o synthetize.
micah94
36

Um método de instância se aplica a uma instância da classe (ou seja, um objeto) enquanto um método de classe se aplica à própria classe.

No C #, um método de classe é marcado como estático. Métodos e propriedades não marcadas como estáticas são métodos de instância.

class Foo {
  public static void ClassMethod() { ... }
  public void InstanceMethod() { ... }
}
Robert Horvick
fonte
1
Argh - desculpe, eu só notei que essa era uma pergunta sobre Obj-C. Espero que minha resposta ainda se aplique, mas vote ou vote para excluir.
Robert Horvick
6
Sem danos causados. A primeira parte da sua resposta está correta como um princípio geral de POO e definitivamente se aplica ao Objetivo-C. Você pode adicionar "objetivo-c" à sua lista de tags para ignorar se não quiser ver essas perguntas, embora qualquer participação seja certamente bem-vinda. :-)
Quinn Taylor
16

A resposta para sua pergunta não é específica para o objetivo-c; no entanto, em diferentes idiomas, os métodos de classe podem ser chamados de métodos estáticos.

A diferença entre métodos de classe e métodos de instância é

Métodos de classe

  • Operar em variáveis ​​de classe (elas não podem acessar variáveis ​​de instância)
  • Não exige que um objeto seja instanciado para ser aplicado
  • Às vezes, pode haver um cheiro de código (algumas pessoas que são novas no OOP usam como muleta para fazer a Programação Estruturada em um ambiente OO)

Métodos de instância

  • Operar em variáveis ​​de instâncias e variáveis ​​de classe
  • Deve ter um objeto instanciado para operar
hhafez
fonte
Métodos de instância podem operar em variáveis ​​de classe?
蘇健豪
16

Eu acho que a melhor maneira de entender isso é olhar alloceinit . Foi essa explicação que me permitiu entender as diferenças.

Método de classe

Um método de classe é aplicado à classe como um todo. Se você verificar o allocmétodo, esse é um método de classe indicado pelo+ declaração anterior à método. É um método de classe porque é aplicado à classe para criar uma instância específica dessa classe.

Método de instância

Você usa um método de instância para modificar uma instância específica de uma classe que é exclusiva para essa instância, e não para a classe como um todo. initpor exemplo (indicado com a -antes da declaração do método), é um método de instância porque você normalmente está modificando as propriedades dessa classe depois que ela foi criada alloc.

Exemplo

NSString *myString = [NSString alloc];

Você está chamando o método de classe allocpara gerar uma instância dessa classe. Observe como o destinatário da mensagem é uma classe.

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

Você está modificando a instância de NSStringchamada myStringdefinindo algumas propriedades nessa instância. Observe como o destinatário da mensagem é uma instância (objeto de classe NSString).

Adam Waite
fonte
O que você quer dizer com verificar o método "assign"? Você pode me indicar um local específico na documentação? (edit) -> ahh deixa pra lá, sim nos docs NSObject diz que em "Tarefas" - developer.apple.com/library/ios/documentation/cocoa/reference/...
Ethan Parker
Você realmente não precisa entender o que realmente faz para entender isso, apenas que é aplicado à classe. Simplificando: allocaloca memória suficiente para o objeto, initmodificará o conteúdo desses endereços de memória para definir o estado do objeto. Não podemos modificar um objeto a menos que haja um espaço para modificá-lo; portanto, usamos allocna classe que decidirá nos dar esse espaço.
Adam Waite
6

Os métodos de classe geralmente são usados ​​para criar instâncias dessa classe

Por exemplo, [NSString stringWithFormat:@"SomeParameter"];retorna uma NSStringinstância com o parâmetro que é enviado a ela. Portanto, por ser um método Class que retorna um objeto de seu tipo, também é chamado de método de conveniência.

iosrookie
fonte
6

Então, se eu entendi direito.

Um classmétodo não precisa que você aloque uma instância desse objeto para usá-lo / processá-lo. Um classmétodo é independente e pode operar sem nenhuma dependência do estado de qualquer objeto dessa classe. classEspera-se que um método aloque memória para todo o seu próprio trabalho e desaloque quando concluído, pois nenhuma instância dessa classe poderá liberar qualquer memória alocada em chamadas anteriores para o método da classe.

UMA instance método é exatamente o oposto. Você não pode chamá-lo, a menos que aloque uma instância dessa classe. É como uma classe normal que tem um construtor e pode ter um destruidor (que limpa toda a memória alocada).

Com maior probabilidade (a menos que você esteja escrevendo uma biblioteca reutilizável, não deve precisar de uma classvariável.

Siddharth
fonte
1
Um caso óbvio em que você precisa de métodos de classe é a criação de instâncias. Você deve ser capaz de criar instâncias sem ter nenhuma instância ainda; caso contrário, a primeira instância nunca poderá ser criada. É por isso que + assign é e deve ser um método de classe.
gnasher729
4

Os métodos de instâncias operam em instâncias de classes (ou seja, "objetos"). Os métodos de classe estão associados a classes (a maioria dos idiomas usa a palavra-chave staticpara esses caras).

eduffy
fonte
3

Tomemos, por exemplo, um jogo em que muitos carros são gerados .. cada um pertence à classe CCar. Quando um carro é instanciado, ele faz uma chamada para

[CCar registerCar:self]

Portanto, a classe CCar pode fazer uma lista de todos os CCar instanciados. Digamos que o usuário termine um nível e queira remover todos os carros ... você pode: 1- Navegar por uma lista de todos os CCar criados manualmente e fazerwhicheverCar.remove(); ou 2- Adicionar um método removeAllCars ao CCar, o que fará isso para você quando ligar para [CCar removeAllCars]. Ou seja, allCars[n].remove();

Ou, por exemplo, você permite que o usuário especifique um tamanho de fonte padrão para todo o aplicativo, que é carregado e salvo na inicialização. Sem o método da classe, talvez você precise fazer algo como

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

Com o método de classe, você pode se safar [FontHandler getDefaultFontSize].

Quanto à função removeVowels, você encontrará que idiomas como C # realmente têm ambos com certos métodos, como toLower ou toUpper.

por exemplo, myString.removeVowels() e String.removeVowels(myString) (em ObjC, seria [String removeVowels:myString]).

Nesse caso, a instância provavelmente chama o método de classe, portanto, ambos estão disponíveis. ie

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

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

basicamente, myString.toLower() chama [String toLower:ownValue]

Não existe uma resposta definitiva, mas se você deseja empurrar um método de classe para melhorar seu código, tente e tenha em mente que um método de classe permitirá apenas que você use outros métodos / variáveis ​​de classe.

foice
fonte
3

métodos de classe

são métodos declarados como estáticos. O método pode ser chamado sem criar uma instância da classe. Os métodos de classe podem operar apenas em membros da classe e não em membros da instância, pois os métodos da classe desconhecem os membros da instância. Os métodos de instância da classe também não podem ser chamados de dentro de um método de classe, a menos que estejam sendo chamados em uma instância dessa classe.

Métodos de instância

por outro lado, exige que uma instância da classe exista antes de poder ser chamada, portanto, é necessário criar uma instância de uma classe usando a nova palavra-chave. Os métodos de instância operam em instâncias específicas de classes. Os métodos de instância não são declarados como estáticos.

iCrazyDev
fonte
Também pode ser criado com a palavra-chave "aloc", não apenas a "nova". Além disso, o Objective-C não exige que exista uma instância para chamar um método de instância; você pode enviar mensagens para um ponteiro nulo.
Elviss Strazdins 11/03/2015
3

No Objective-C, todos os métodos começam com um caractere "-" ou "+". Exemplo:

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

+ (void) classMethod;
@end

Os caracteres "+" e "-" especificam se um método é um class methodou uminstance method respectivamente.

A diferença seria clara se chamarmos esses métodos. Aqui os métodos são declarados emMyClass .

instance method requer uma instância da classe:

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

Dentro de MyClassoutros métodos, podemos chamar métodos de instância de MyClassuso self:

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

Mas, class methodsdeve ser chamado na própria classe:

[MyClass classMethod];

Ou:

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

Isso não vai funcionar:

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

MÉTODOS DE CLASSE


Um método de classe normalmente cria uma nova instância da classe ou recupera algumas propriedades globais da classe. Os métodos de classe não operam em uma instância ou têm acesso à variável de instância.


MÉTODOS DE INSTALAÇÃO


Um método de instância opera em uma instância específica da classe. Por exemplo, o método de acesso que você implementou são todos os métodos de instância. Você os utiliza para definir ou obter as variáveis ​​de instância de um objeto específico.


INVOCAR


Para invocar um método de instância, você envia a mensagem para uma instância da classe.

Para invocar um método de classe, você envia a mensagem diretamente para a classe.


Fonte: IOS - Objective-C - Métodos de classe e métodos de instância

Nam N. HUYNH
fonte
1

Os métodos de classe não podem alterar ou conhecer o valor de qualquer variável de instância. Esse deve ser o critério para saber se um método de instância pode ser um método de classe.

Deepee
fonte
-1 de mim, porque você pode passar a instância para o método de classe e ele poderá alterar e saber os valores das variáveis.
Elviss Strazdins 11/03/2015
1

Lembre-se também de que a mesma ideia se aplica a variáveis. Você encontrará termos como estático, membro, instância, classe e assim por diante ao falar sobre variáveis ​​da mesma maneira que faria para métodos / funções.

Parece que o termo comum na comunidade Obj-C é variável por exemplo, mas eu ainda não sou um garoto de Obj-C.

Meio duplex
fonte
1

Uma atualização para as respostas acima, concordo que os métodos de instância usam uma instância de uma classe, enquanto um método de classe pode ser usado apenas com o nome da classe.

Não há mais nenhuma diferença entre o método de instância e o método de classe após a contagem automática de referência existir no Objective-C.

Por exemplo, [NS StringWithformat:..]um método de classe e [[NSString alloc] initwihtformat:..]um método de instância, ambos são os mesmos após o ARC

user1292809
fonte
1

Nota: Isso é apenas no formato de pseudo-código

Método de classe

Quase tudo o que precisa fazer é durante o tempo de compilação . Ele não precisa de nenhuma entrada do usuário, nem o cálculo é baseado em uma instância. Tudo sobre isso é baseado na classe / projeto - que é único, ou seja, você não possui vários projetos para uma classe. Você pode ter variações diferentes durante o tempo de compilação? Não, portanto, a classe é única e, portanto, não importa quantas vezes você chame um método de classe, o ponteiro apontando para ele seria o mesmo.

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

Método de instância

Por outro lado, o método da instância ocorre durante o tempo de execução, pois somente então você criou uma instância de algo que pode variar a cada instanciação.

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.

Se você vem de outros idiomas, os métodos estáticos são iguais aos métodos de classe.
Se você é do Swift, os métodos de tipo são iguais aos métodos de classe.

Mel
fonte
0

Adicionando às respostas acima

O método Class funcionará na classe, vamos usá-lo para fins gerais, como + stringWithFormat, tamanho da classe e, o mais importante, para init etc

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

O método de instância funcionará em uma instância de uma classe e não em uma classe como se estivéssemos tendo duas pessoas e queremos conhecer o saldo de cada uma separadamente aqui, precisamos usar o método de instância. Porque não retornará resposta geral. por exemplo, como determinar a contagem de NSSArray etc.

[johnson getAccountBalance];
[ankit getAccountBalance];
Ankit garg
fonte