В чем разница между методами класса и экземпляра?

448

В чем разница между методом класса и методом экземпляра?

Являются ли методы экземпляра средствами доступа (геттерами и сеттерами), в то время как методы класса являются почти всем остальным?

посвященный
источник

Ответы:

673

Как говорилось в большинстве других ответов, методы экземпляра используют экземпляр класса, тогда как метод класса может использоваться только с именем класса. В Objective-C они определены следующим образом:

@interface MyClass : NSObject

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

@end

Затем они могут быть использованы так:

[MyClass aClassMethod];

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

Некоторыми реальными примерами методов класса являются удобные методы для многих базовых классов, таких как NSString« +stringWithFormat:или NSArray» +arrayWithArray:. Метод экземпляра будет NSArray«S -countметод.

Кори Килгер
источник
7
Хороший ответ. Стоит также отметить, что вы увидите конкретную сокращенную запись для описания методов. Например, + [NSString stringWithFormat:] является методом класса + stringWithFormat: on NSString; - [NSArray objectAtIndex:] является методом экземпляра. Методы с несколькими частями селектора пишутся как - [NSMutableDictionary setObject: forKey:] и т. Д. Вы часто будете видеть это примечание в ответах Какао, документации и в Xcode.
Куинн Тейлор
149
Я бы добавил, что метод класса называется «статическим» методом во многих других языках. И чтобы ответить на первоначальный вопрос, методы доступа являются методами экземпляра, поскольку они устанавливают и получают состояние определенного экземпляра. В приведенном выше примере NSArray count возвращает количество объектов в конкретном экземпляре.
Брайан Пан
2
«тогда как метод класса может использоваться только с именем класса». или объект класса
user102008
2
Извините за волнение ... но я только что узнал разницу и ее потенциал. методы класса рок и классы синглтона! Уффф, я влюбился! <3
Паван
2
Статические методы @BrianPan и методы классов не совпадают. Они похожи, но причина, по которой они называются по-разному, заключается в том, что они работают по-разному. Например, статические методы не могут быть переопределены.
Sulthan
190

Все технические детали были хорошо описаны в других ответах. Я просто хочу поделиться простой аналогией, которая, на мой взгляд, прекрасно иллюстрирует разницу между классом и экземпляром:

введите описание изображения здесь

Класс похож на план дома: У вас есть только один план , и (обычно) вы не можете сделать это много с одним только планом.

введите описание изображения здесь

Экземпляр (или объект ) является фактическим домом , который вы строите на основе плана: Вы можете построить множество домов из того же плана. Затем вы можете покрасить стены в разные цвета в каждом из домов, точно так же, как вы можете независимо изменять свойства каждого экземпляра класса, не затрагивая другие экземпляры.

Йоханнес Фаренкруг
источник
6
@JohannesFahrenkrug Хорошо объяснил концепцию класса и объекта здесь. Это не фактический вопрос для difference between class method and an instance method ;
Шеху
1
Прекрасное объяснение класса против экземпляра класса. Классы являются странным понятием для новичков, и это объясняет это самым фундаментальным образом.
Алекс МакФерсон
1
@JohannesFahrenkrug действительно хорошее объяснение, которое заставило меня задуматься о том, как использовать оба
варианта
1
Такое великолепное объяснение :)
Praveenkumar
1
Хорошая аналогия. Пожалуйста, дайте этому парню годовой запас пиццы.
GeneCode
102

Как и в других ответах, методы экземпляра работают с объектом и имеют доступ к его переменным экземпляра, в то время как метод класса работает с классом в целом и не имеет доступа к переменным конкретного экземпляра (если вы не передаете экземпляр как параметр).

Хорошим примером метода класса является метод счетного типа, который возвращает общее количество экземпляров класса. Методы класса начинаются с a +, а экземпляры класса начинаются с -. Например:

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

Выход: Возраст: 0 Количество человек: 2

Другой пример - если у вас есть метод, который вы хотите, чтобы пользователь мог вызывать, иногда полезно сделать его методом класса. Например, если у вас есть класс с именем MathFunctions, вы можете сделать это:

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

Тогда пользователь будет звонить:

[MathFunctions square:34];

без необходимости создавать экземпляр класса!

Вы также можете использовать функции класса для возврата автоматически выпущенных объектов, таких как NSArray

+ (NSArray *)arrayWithObject:(id)object

Это берет объект, помещает его в массив и возвращает автоматически выпущенную версию массива, которая не должна управляться памятью, отлично подходит для временных массивов, а что нет.

Я надеюсь, что теперь вы понимаете, когда и / или почему вы должны использовать методы класса !!

micmoo
источник
1
micmoo, могу я предложить вам поставить "static int numberOfPeople = 0;" в коде отформатированный текст? Я был в замешательстве, пока не заметил это над примером кода. Кроме этого, очень краткий ответ.
mobibob
2
Извините за путаницу с новичком, но зачем вам нужна переменная экземпляра "age" и метод экземпляра "age"? Не получится ли с помощью @synthetize получить и получить переменную "age" для экземпляра?
selytch
@selytch "age" должен быть определен как свойство для использования synthetize.
micah94
36

Метод экземпляра применяется к экземпляру класса (то есть объекту), тогда как метод класса применяется к самому классу.

В C # метод класса помечен как статический. Методы и свойства, не помеченные как статические, являются методами экземпляра.

class Foo {
  public static void ClassMethod() { ... }
  public void InstanceMethod() { ... }
}
Роберт Хорвик
источник
1
Извините, я только что заметил, что это был вопрос Obj-C. Надеюсь, мой ответ по-прежнему применим, но, пожалуйста, проголосуйте против или проголосуйте за удаление.
Роберт Хорвик
6
Без вреда. Первая часть вашего ответа верна как общий принцип ООП и определенно относится к Objective-C. Вы можете добавить «target-c» в свой список тегов, чтобы игнорировать, если вы не хотите видеть такие вопросы, хотя любое участие, безусловно, приветствуется. :-)
Куинн Тейлор
16

Ответ на ваш вопрос не является специфичным для target-c, однако в разных языках методы класса могут называться статическими методами.

Разница между методами класса и методами экземпляра

Методы класса

  • Работа с переменными класса (они не могут получить доступ к переменным экземпляра)
  • Не требует, чтобы объект был создан для применения
  • Иногда может быть запах кода (некоторые люди, которые плохо знакомы с ООП, используют в качестве опоры для выполнения структурированного программирования в среде ОО)

Методы экземпляра

  • Работа с переменными экземпляров и переменными класса
  • Должен иметь инстанцированный объект для работы
hhafez
источник
Методы экземпляра могут работать с переменными класса?
蘇健豪
16

Я думаю , что лучший способ понять это , чтобы смотреть на allocи init. Именно это объяснение позволило мне понять различия.

Метод класса

Метод класса применяется к классу в целом. Если вы проверите allocметод, это метод класса, обозначенный+ перед объявлением метода. Это метод класса, потому что он применяется к классу для создания конкретного экземпляра этого класса.

Метод экземпляра

Вы используете метод экземпляра для изменения конкретного экземпляра класса, который является уникальным для этого экземпляра, а не для класса в целом. initнапример (обозначается -перед объявлением метода), является методом экземпляра, потому что вы обычно изменяете свойства этого класса после того, как он был создан с помощью alloc.

пример

NSString *myString = [NSString alloc];

Вы вызываете метод класса allocдля генерации экземпляра этого класса. Обратите внимание, что получатель сообщения является классом.

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

Вы изменяете экземпляр NSStringвызванного myString, устанавливая некоторые свойства для этого экземпляра. Обратите внимание, что получатель сообщения является экземпляром (объектом класса NSString).

Адам Уэйт
источник
Что вы подразумеваете под проверкой метода «alloc»? Можете ли вы указать мне конкретное место в документации? (edit) -> ааа, неважно, да, в документах NSObject говорится, что в разделе «Задачи» - developer.apple.com/library/ios/documentation/cocoa/reference/…
Этан Паркер,
Вам не нужно понимать, что он делает, чтобы понять это, просто то, что он применяется к классу. Проще говоря: allocвыделяет достаточно памяти для объекта, initизменит то, что находится в этих адресах памяти, чтобы определить состояние объекта. Мы не можем изменить объект, если нет места для его изменения, поэтому мы используем allocкласс, который определит, предоставим ли нам это пространство.
Адам Уэйт
6

Методы класса обычно используются для создания экземпляров этого класса

Например, [NSString stringWithFormat:@"SomeParameter"];возвращает NSStringэкземпляр с параметром, который ему отправлен. Следовательно, поскольку это метод класса, который возвращает объект своего типа, его также называют вспомогательным методом.

iosrookie
источник
6

Так что, если я правильно понимаю.

classМетод не требует , чтобы вы выделить экземпляр этого объекта к использованию / обработать его. classМетод является автономным и может работать без какого - либо зависимости от состояния любого объекта этого класса. Ожидается, что classметод выделит память для всей своей работы и освободит ее по завершении, поскольку ни один экземпляр этого класса не сможет освободить память, выделенную в предыдущих вызовах метода класса.

instanceМетод как раз наоборот. Вы не можете вызвать его, если не выделите экземпляр этого класса. Это как обычный класс, который имеет конструктор и может иметь деструктор (который очищает всю выделенную память).

По всей вероятности (если вы пишете библиотеку многократного использования, вам не нужна classпеременная).

Сиддхарт
источник
1
Очевидным случаем, когда вам нужны методы класса, является создание экземпляров. Вы должны иметь возможность создавать экземпляры без каких-либо экземпляров, иначе первый экземпляр никогда не будет создан. Вот почему + alloc является и должен быть методом класса.
gnasher729
4

Методы экземпляров работают с экземплярами классов (т. Е. «Объектами»). Методы класса связаны с классами (большинство языков используют ключевое слово staticдля этих парней).

eduffy
источник
3

Возьмем, к примеру, игру, в которой появляется множество автомобилей. Каждый из них принадлежит к классу CCar. Когда автомобиль создается, он звонит

[CCar registerCar:self]

Таким образом, класс CCar может составить список каждого экземпляра CCar. Допустим, пользователь заканчивает уровень и хочет удалить все машины ... вы можете либо: 1- просмотреть список всех созданных вами CCar вручную, whicheverCar.remove(); либо выполнить или 2- добавить метод removeAllCars в CCar, что сделает это. для вас, когда вы звоните [CCar removeAllCars]. Т.е. allCars[n].remove();

Или, например, вы позволяете пользователю указать размер шрифта по умолчанию для всего приложения, которое загружается и сохраняется при запуске. Без метода класса вам, возможно, придется сделать что-то вроде

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

С помощью метода класса вы могли бы сойти с рук [FontHandler getDefaultFontSize] .

Что касается вашей функции removeVowels, вы обнаружите, что языки, подобные C #, на самом деле имеют оба метода с определенными методами, такими как toLower или toUpper.

например, myString.removeVowels() и String.removeVowels(myString) (в ObjC это будет[String removeVowels:myString] ).

В этом случае экземпляр, скорее всего, вызывает метод класса, поэтому оба доступны. т.е.

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

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

в принципе, myString.toLower() звонки [String toLower:ownValue]

Нет однозначного ответа, но если вы чувствуете, что использование метода класса улучшит ваш код, попробуйте и помните, что метод класса позволит вам использовать только другие методы / переменные класса.

sicklebrick
источник
3

методы класса

являются методами, которые объявлены как статические. Метод может быть вызван без создания экземпляра класса. Методы класса могут работать только с членами класса, а не с членами экземпляра, поскольку методы класса не знают членов экземпляра. Методы экземпляра класса также нельзя вызывать из метода класса, если они не вызываются для экземпляра этого класса.

Методы экземпляра

с другой стороны, требуется, чтобы экземпляр класса существовал до их вызова, поэтому необходимо создать экземпляр класса с помощью ключевого слова new. Методы экземпляра работают с конкретными экземплярами классов. Методы экземпляра не объявляются как статические.

iCrazyDev
источник
Он также может быть создан с помощью ключевого слова «alloc», а не только «new». Кроме того, Objective-C не требует существования экземпляра для вызова метода экземпляра, вы можете отправлять сообщения с нулевым указателем.
Элвисс Страздиньш
3

В Objective-C все методы начинаются с символа «-» или «+». Пример:

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

+ (void) classMethod;
@end

Символы «+» и «-» указывают, является ли метод a class methodили a instance methodсоответственно.

Разница будет понятна, если мы вызовем эти методы. Здесь методы объявлены в MyClass.

instance method Требовать экземпляр класса:

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

Внутри MyClassдругих методов можно вызывать методы экземпляра MyClassusing self:

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

Но, class methodsдолжен быть вызван сам класс:

[MyClass classMethod];

Или:

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

Это не сработает:

// Error
[myClass classMethod];
// Error
[self classMethod];
Тулона
источник
3

МЕТОДЫ КЛАССА


Метод класса обычно либо создает новый экземпляр класса, либо извлекает некоторые глобальные свойства класса. Методы класса не работают с экземпляром или не имеют доступа к переменной экземпляра.


МЕТОДЫ ИНСТАНЦИИ


Метод экземпляра работает с конкретным экземпляром класса. Например, реализованный вами метод доступа - это все методы экземпляра. Вы используете их для установки или получения переменных экземпляра определенного объекта.


ВЫЗОВ


Чтобы вызвать метод экземпляра, вы отправляете сообщение экземпляру класса.

Чтобы вызвать метод класса, вы отправляете сообщение классу напрямую.


Источник: IOS - Objective-C - Методы класса и методы экземпляра

Нам Н. ХУЙНХ
источник
1

Методы класса не могут изменить или узнать значение любой переменной экземпляра. Это должно быть критерием для того, чтобы знать, может ли метод экземпляра быть методом класса.

Deepee
источник
-1 от меня, потому что вы можете передать экземпляр в метод класса, и он сможет изменять и знать значения своих переменных.
Эльвисс Страздиньш
1

Также помните, что та же идея относится и к переменным. Вы встретите такие термины, как static, member, instance, class и т. Д., Когда говорите о переменных так же, как и для методов / функций.

Кажется, что общий термин в сообществе Obj-C - это ivar, например, переменная, но я пока не парень из Obj-C.

Полудуплекс
источник
1

Обновление вышеупомянутых ответов, я согласен, методы экземпляра используют экземпляр класса, тогда как метод класса может использоваться только с именем класса.

Больше нет никакой разницы между методом экземпляра и методом класса после того, как в Objective-C появился автоматический подсчет ссылок.

Например, [NS StringWithformat:..]метод класса и метод [[NSString alloc] initwihtformat:..]экземпляра, оба одинаковы после ARC

user1292809
источник
1

Примечание: это только в формате псевдокода

Метод класса

Почти все, что нужно сделать, это во время компиляции . Он не нуждается ни в каком пользовательском вводе, ни его вычисление основано на экземпляре. Все в нем основано на классе / чертеже, который уникален, т.е. у вас нет нескольких чертежей для одного класса. У вас могут быть разные вариации во время компиляции? Нет, поэтому класс является уникальным, и поэтому независимо от того, сколько раз вы вызываете метод класса, указатель на него будет одинаковым.

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

Метод экземпляра

Наоборот, метод экземпляра происходит во время выполнения, поскольку только тогда вы создали экземпляр чего-либо, что может варьироваться при каждом создании.

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.

Если вы пришли из других языков, статические методы такие же, как методы класса.
Если вы пришли из Swift, методы типа такие же, как методы класса.

Мед
источник
0

Добавление к ответам выше

Метод класса будет работать с классом, мы будем использовать его для общего назначения, например: + stringWithFormat, размер класса и, что наиболее важно, для init и т. Д.

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

Метод экземпляра будет работать с экземпляром класса, а не с классом, как если бы у нас было два человека, и мы хотим узнать баланс каждого отдельно, здесь нам нужно использовать метод экземпляра. Потому что это не вернет общий ответ. например, как определить количество NSSArray и т. д.

[johnson getAccountBalance];
[ankit getAccountBalance];
Анкит Гарг
источник