Чим відрізняються методи класу та екземпляра?


Відповіді:


673

Як і більшість інших відповідей, сказаних, методи екземплярів використовують екземпляр класу, тоді як метод класу можна використовувати лише з назвою класу. У Objective-C вони визначаються таким чином:

@interface MyClass : NSObject

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

@end

Потім їх можна використовувати так:

[MyClass aClassMethod];

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

Деякі приклади реального світу методів класу - це зручні методи для багатьох класів Foundation, таких як NSString's +stringWithFormat:або NSArray' +arrayWithArray:. Метод примірника буде NSArray«S -countметод.


7
Хороша відповідь. Варто також зазначити, що ви побачите певну скорочену позначення для опису методів. Наприклад, + [NSString stringWithFormat:] - метод класу + stringWithFormat: у NSString; - [NSArray objectAtIndex:] - метод примірника. Методи з декількома частинами селектора записуються як - [NSMutableDictionary setObject: forKey:] і т. Д. Ви часто будете бачити цю нотацію у відповідях, документації та какао в какао.
Квінн Тейлор

149
Я додам, що метод класу називається "статичним" методом у багатьох інших мовах. І щоб відповісти на початкове запитання, аксесоари - це методи екземпляра, оскільки вони встановлюють і отримують стан конкретного екземпляра. У вищенаведеному прикладі кількість NSArray повертає кількість об'єктів у конкретному екземплярі.
Брайан Пан

2
"тоді як метод класу можна використовувати лише з назвою класу." або об’єкт класу
user102008

2
Вибачте за своє хвилювання ... але я просто дізнався різницю та її потенціал. методи класу рок і так само однокласні класи! ufff Я закохався! <3
Паван

2
@BrianPan статичні та класичні методи не однакові. Вони схожі, але причина, яку вони називають по-різному, полягає в тому, що вони працюють по-різному. Наприклад, статичні методи не можна перекрити.
Султан

190

Усі технічні деталі були добре висвітлені в інших відповідях. Я просто хочу поділитися простою аналогією, яка, на мою думку, добре ілюструє різницю між класом та екземпляром:

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

Клас схожий на план будинку: У вас є тільки один план , і (зазвичай) ви не можете зробити це багато з одним тільки планом.

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

Примірник (або об'єкт ) є фактичним будинком , який ви будуєте на основі плану: Ви можете побудувати безліч будинків з того ж плану. Потім можна пофарбувати стіни різним кольором у кожному з будинків, так само як ви можете самостійно змінити властивості кожного екземпляра класу, не впливаючи на інші екземпляри.


6
@JohannesFahrenkrug Добре пояснив тут поняття класу та об'єкта. Хіба це не справжнє питання difference between class method and an instance method ;
Шеху

1
Ідеальне пояснення класу проти екземпляра класу. Заняття - це дивне поняття для новачків, і це пояснюється це найбільш принципово.
Алекс Макферсон

1
@JohannesFahrenkrug справді гарне пояснення, яке змусило мене подумати, як обидва
г відрізняються

1
Таке чудове пояснення :)
Praveenkumar

1
Гарна аналогія. Будь ласка, хтось дасть цьому хлопцеві рік піци.
GeneCode

102

Як і в інших відповідях, методи екземплярів діють на об'єкт і мають доступ до змінних його екземплярів, тоді як метод класу працює над класом в цілому і не має доступу до змінних конкретного примірника (якщо ви не передаєте екземпляр у вигляді параметр).

Хорошим прикладом методу класу є метод зустрічного типу, який повертає загальну кількість екземплярів класу. Методи класу починаються з а +, а екземпляри починаються з -. Наприклад:

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

Це бере об’єкт, ставить його в масив і повертає опубліковану версію масиву, який не повинен керуватися пам'яттю, відмінно підходить для температурних масивів, а що ні.

Я сподіваюся, що тепер ви зрозуміли, коли і / або для чого слід використовувати методи класу !!


1
micmoo, я можу запропонувати вам поставити "static int numberOfPeople = 0;" у тексті, відформатованому кодом? Я плутався, поки не помітив це над зразком коду. Крім цього, дійсно стисла відповідь.
mobibob

2
Вибачте моєму непорозумінні, але навіщо вам потрібна змінна інстанція "вік" та метод екземпляра "вік"? Не вдасться створити геттер і сетер, наприклад, змінну "вік" за допомогою @synthetize?
selytch

@selytch "вік" повинен був бути визначений як властивість, щоб використовувати синтез.
micah94

36

Метод екземпляра застосовується до екземпляра класу (тобто об'єкта), тоді як метод класу застосовується до самого класу.

У C # метод класу позначений статичним. Методи та властивості, не позначені статичними, є методами екземплярів.

class Foo {
  public static void ClassMethod() { ... }
  public void InstanceMethod() { ... }
}

1
Арг - вибачте, я щойно помітив, що це питання Obj-C. Сподіваюсь, моя відповідь все-таки діє, але, будь ласка, проголосуйте або проголосуйте, щоб видалити.
Роберт Горвік

6
Шкоди не завдано. Перша частина вашої відповіді правильна як загальний принцип ООП, і вона безумовно стосується Цілі-С. Ви можете додати "target-c" до свого списку тегів, щоб їх ігнорувати, якщо ви не хочете бачити подібні запитання, хоча будь-яка участь, безумовно, вітається. :-)
Квінн Тейлор

16

Відповідь на ваше запитання не характерна для цілі-c, проте в різних мовах методи Класу можуть називатися статичними методами.

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

Класові методи

  • Робота з змінними Class (вони не можуть отримати доступ до змінних екземплярів)
  • Не вимагайте, щоб об’єкт міг бути використаний для застосування
  • Іноді може бути запах коду (деякі люди, які не знайомі з OOP, використовують як милицю, щоб робити Структурне програмування в середовищі ОО)

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

  • Працювати над змінними екземплярами та змінними класу
  • Повинно мати об'єкт, який функціонує, для роботи

Методи екземплярів можуть діяти на змінних класу?
蘇健豪

16

Я думаю, що найкращий спосіб зрозуміти це - подивитися allocі init. Саме це пояснення дозволило мені зрозуміти відмінності.

Метод класу

Метод класу застосовується до класу в цілому. Якщо ви перевіряєте allocметод, це метод класу, позначений +попередньою заявою методу. Це метод класу, оскільки він застосовується до класу для створення конкретного примірника цього класу.

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

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

Приклад

NSString *myString = [NSString alloc];

Ви викликаєте метод класу alloc, щоб генерувати екземпляр цього класу. Зверніть увагу, як одержувач повідомлення є класом.

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

Ви змінюєте екземпляр NSStringвиклику myString, встановлюючи деякі властивості для цього примірника. Зверніть увагу, яким одержувачем повідомлення є екземпляр (об’єкт класу NSString).


Що ви маєте на увазі, перевіривши метод "алока"? Чи можете ви вказати мені певне місце в документації? (редагувати) -> ах ніколи не пам’ятайте, так, у документах NSObject написано, що під «Завданнями» - developer.apple.com/library/ios/documentation/cocoa/reference/…
Етан Паркер

Вам не потрібно розуміти, що це насправді, щоб зрозуміти це, лише те, що воно застосовується до класу. Простіше кажучи: allocвиділяє достатню кількість пам’яті для об’єкта, initзмінює те, що знаходиться в цих адресах пам'яті, щоб визначити стан об’єкта. Ми не можемо змінити об'єкт, якщо не буде місця для його модифікації, тому ми використовуємо allocклас, який вирішить дати нам цей простір.
Адам Уайт

6

Методи класу зазвичай використовуються для створення примірників цього класу

Наприклад, [NSString stringWithFormat:@"SomeParameter"];повертає NSStringекземпляр з параметром, який йому надісланий. Отже, оскільки це метод Class, який повертає об'єкт свого типу, його також називають зручним методом.


6

Тож якщо я правильно це розумію.

Для використання classметоду не потрібно виділяти примірник цього об'єкта для його використання / обробки. classМетод є автономним і може працювати без будь - якої залежності від стану будь-якого об'єкта цього класу. Аclass метод виділить пам'ять на всю її власну роботу і розмістить її після завершення, оскільки жоден екземпляр цього класу не зможе звільнити будь-яку пам'ять, виділену в попередніх викликах методу класу.

instanceМетод як раз навпаки. Ви не можете його викликати, якщо не виділите екземпляр цього класу. Це як звичайний клас, який має конструктор і може мати деструктор (що очищає всю виділену пам'ять).

З найбільшою часткою ймовірності (якщо ви не пишете бібліотеку для багаторазового використання, вам не знадобиться classзмінна.


1
Очевидним випадком, коли вам потрібні методи класу, є створення екземплярів. Ви повинні бути в змозі створити екземпляри, не маючи жодних примірників, інакше перший екземпляр ніколи не може бути створений. Ось чому + alloc є і повинен бути методом класу.
gnasher729

4

Методи екземплярів працюють на екземплярах класів (тобто "об'єктах"). Методи класу пов'язані з класами (більшість мов використовують staticдля цих хлопців ключове слово ).


3

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

[CCar registerCar:self]

Таким чином, клас CCar, може скласти список кожного CCar, створений. Скажімо, користувач закінчує рівень і хоче видалити всі машини ... ви можете: 1- Перейти список кожного створеного вами CCar вручну, або виконати, whicheverCar.remove(); або 2 - Додати метод CCAAAllCars до 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]

Однозначної відповіді немає, але якщо ви відчуваєте, що введення методу класу в поліпшить ваш код, попросіть його і врахуйте, що метод класу дозволить вам використовувати лише інші методи / змінні класу.


3

методи класу

- це методи, які оголошені статичними. Метод можна викликати без створення екземпляра класу. Методи класу можуть діяти лише для членів класу, а не для членів екземпляра, оскільки методи класу не знають про членів екземпляра. Методи екземплярів класу також не можна викликати з методу класу, якщо вони не викликаються в екземплярі цього класу.

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

з іншого боку, вимагає існування екземпляра класу до того, як їх можна буде викликати, тому екземпляр класу потрібно створити за допомогою нового ключового слова. Методи екземплярів працюють на конкретних екземплярах класів. Методи екземплярів не оголошуються статичними.


Він також може бути створений за допомогою ключового слова "alloc" не тільки "нового". Також Objective-C не вимагає існування екземпляра для виклику методу екземпляра, ви можете відправляти повідомлення на нульовий покажчик.
Елвіс Страздінс

3

У Objective-C всі методи починаються з символу "-" або "+". Приклад:

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

+ (void) classMethod;
@end

Символи "+" та "-" задають, чи метод є a class methodчи aninstance method відповідно.

Різниця була б зрозумілою, якби ми називали ці методи. Тут методи оголошені в MyClass.

instance method потрібен примірник класу:

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

Всередині MyClassінших методів можна викликати екземплярні методи MyClassвикористання self:

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

Але, class methodsтреба викликати сам клас:

[MyClass classMethod];

Або:

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

Це не спрацює:

// Error
[myClass classMethod];
// Error
[self classMethod];

3

МЕТОДИ КЛАСУ


Метод класу, як правило, або створює новий екземпляр класу, або отримує деякі глобальні властивості класу. Методи класу не працюють на екземплярі або не мають доступу до змінної екземпляра.


ІНСТАНЦІЙНІ МЕТОДИ


Метод екземпляра працює на конкретному екземплярі класу. Наприклад, реалізований вами метод accessors - це всі методи екземпляра. Ви використовуєте їх для встановлення або отримання змінних екземплярів певного об'єкта.


ВИКОНАТИ


Щоб викликати метод екземпляра, ви надсилаєте повідомлення екземпляру класу.

Щоб викликати метод класу, ви надсилаєте повідомлення безпосередньо класу.


Джерело: IOS - Objective-C - Методи класу та методи екземплярів


1

Методи класу не можуть змінити або знати значення будь-якої змінної примірника. Це має бути критерієм для того, щоб знати, чи метод екземпляра може бути методом класу.


-1 від мене, тому що ви можете передати екземпляр методу класу, і він зможе змінити і знати, що це значення змінних.
Елвіс Страздінс

1

Також пам’ятайте, що ця ж ідея стосується змінних. Ви будете стикатися з такими термінами, як статичні, член, екземпляр, клас і так далі, коли будете говорити про змінні такі ж, як і для методів / функцій.

Здається, загальним терміном у спільноті Obj-C є ivar, наприклад, змінна, але я ще не хлопець Obj-C.


1

Оновлення вищезазначених відповідей, я погоджуюсь, що методи екземпляра використовують екземпляр класу, тоді як метод класу можна використовувати лише з назвою класу.

Існує НІ більше різниці між методом екземпляра і методом класу після автоматичного підрахунку посилань, що виникли в Objective-C.

Для прикладу [NS StringWithformat:..]метод класу та [[NSString alloc] initwihtformat:..]метод екземпляра обидва однакові після ARC


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

Додавання до вищезазначених відповідей

Метод класу буде працювати над класом, ми будемо використовувати це для загальних цілей, де like + stringWithFormat, розмір класу та найголовніше для init тощо

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

Метод екземпляра буде працювати на екземплярі класу, а не на класі, як у нас є дві людини, і ми хочемо ознайомитись з балансом кожного окремо, тут нам потрібно використовувати метод екземпляра. Тому що це не поверне загальну відповідь. наприклад, як визначити кількість NSSArray і т.д.

[johnson getAccountBalance];
[ankit getAccountBalance];
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.