Коли вводяться в дію "статичні функції"?


25

Гаразд, я дізнався, що таке статична функція, але я досі не бачу, чому вони корисніші, ніж функції приватних членів. Це може бути тут новим питанням, але чому б просто не замінити всі функції приватних членів статичними функціями?


1
Чи не слід це "замінювати всі статичні функції приватними членами"? Наразі ви заявляєте, що не бачите сенсу статичних методів і продовжуєте запитувати, чому ми не використовуємо більше з них.

5
Що таке "статична функція"? У C ++ є щонайменше два значення (і востаннє я подивився на чернетки C ++ 11, вони видалили повідомлення про анулювання, staticоскільки вони обмежували функції для завантаження області.
Девід Торнлі

Ви маєте на увазі "статичну функцію" у значенні функціональної вільної статичної функції в області C / C ++, або як "статичну функцію / метод мембрани"? Це величезна різниця!
Ян Худек

@JanHudec: Я думаю, що, зважаючи на наявність, private memberми можемо сміливо припустити, що ОП запитує про концепцію ОО і не має поняття про статику обсягу файлів.
Матьє М.

@MatthieuM. Насправді саме присутність "приватного члена" - саме те, що змушує мене вважати, що він має на увазі статичні функції в сенсі С ++. Оскільки статичні функції, пов’язані з файлами, та функції приватного члена - це дві речі, які мають дуже подібне використання в C ++, тоді як заміна публічного статичного члена приватним нестатичним членом просто не має особливого сенсу. На жаль, ОП, схоже, не реагує.
Ян Худек

Відповіді:


25

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

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


Дякую, Бернард. Btw, ти знаєш, що означає компілятор "прив’язати метод до класу"?
Темний тамплієр

@Dark Templar: Не можу сказати, що я роблю. Це специфічно для певної мови?
Бернар

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

@newprint: Ти маєш рацію, однак це не те, що я сказав. Я сказав, коли вони не залежать від членів класу. Використання статичних членів добре, якщо вони необхідні, але це може бути не завжди так.
Бернард

8

Спроба більш спрощеного пояснення, ніж вище (досить хороші).

Об'єкт - це звичайно код + дані. Статичний метод застосовується, коли у вас є лише частина "коду", з якою потрібно працювати (немає даних / стану, які підтримуються (крім статичних членів даних)).


5

Тому що вони не потребують примірника і можуть бути загальнодоступними. Скажімо, вам потрібна функція для отримання найбільшого спільного знаменника (GCD; дуже корисно для класів дробів; і так, це просто простий приклад). Немає сенсу створювати клас об’єктів, єдиною метою якого є те, що ви можете мати thisвказівник, який вам ні потрібен, ні не використовує gcd. Отже, ви використовуєте статичний метод для нього, в ідеалі для класу, який фактично використовує GCD (наприклад, у класі дробів).

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


Чи не було б краще у вашому прикладі використовувати безкоштовну функцію?
Ela782

2
@ Ela782 Якщо мова має вільні функції, так.

Добре, дякую за запевнення. Цю найкращу практику я дізнався лише нещодавно. Однак тоді у мене зараз виникають труднощі бачити, коли статична функція члена статистика може бути корисною, скажімо, такою мовою, як C ++. Випадок використання для обох - це те, коли функція не залежить або потрібен екземпляр класу, і тоді безкоштовні функції є рекомендацією. Можливо, це має бути новим питанням.
Ela782

1
@ Ela782 Так, це може спричинити прекрасне запитання. Дві швидкі моменти: спеціально для C ++ статичні члени корисні для мета програмування шаблонів, оскільки ви можете передавати тип як шаблон шаблону, але не простір імен. Взагалі статичні функції можна використовувати, щоб вказати, що функція дійсно тісно належить до якогось класу, на відміну від простої приналежності в просторі імен (думаю stuff::Thing::Load(...)проти stuff::LoadThing()).

2

Я використовую їх як допоміжні функції для поширених завдань, наприклад:

  • Перетворення градусів у радіани (і навпаки);
  • Намотування струни;
  • Перетворення з перерахунку на щось інше (у цьому проекті я працюю, вони виступають як хеш-таблиця);

Більшість моїх файлів, які групують статичні функції, мають суфікс Helper, тобто це те, що вони роблять, допомагає мені швидше кудись дістатися.


2

Щодо статичного методу:

Статичні методи ні вимагають екземпляра класу, ні вони можуть неявно отримувати доступ до даних (або цього, самості, я і т. Д.) Такого екземпляра. [ 1 ]

Приклади, коли корисні статичні методи:

  • Глобальні / хелперні методи
  • Отримання результатів запитів із класу Модель даних (виклик SP)

Просто використовуйте їх там, де це можливо.

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

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


1

Статичні та приватні насправді є ортогональними: метод може бути статичним, приватним, або жодним, або обом.

Статичні та нестатичні (також "методи екземпляра") вказують, чи метод працює над самим класом (статичним) або одним конкретним екземпляром (нестатичний). Залежно від мови, ви можете викликати статичний метод через екземпляр, але ви ніколи не можете отримати доступ до екземпляра за допомогою статичного методу (що також означає, що ви не можете викликати будь-які нестатичні методи всередині статичного методу, просто тому, що у вас немає thisоб’єкт). Використовуйте статичні методи для реалізації поведінки, яка концептуально пов'язана з класом, але не "прив'язується" до одного конкретного екземпляра. Інший сценарій, коли ви можете використовувати статичні методи, це коли у вас є функція, яка працює на двох екземплярах класу, і жоден операнд не заслуговує на привілейований статус - наприклад, якщо у вас є класVector, і ви хочете реалізувати додавання; ваш метод додавання можна назвати як a.Add(b), але, Vector.Add(a, b)ймовірно, має більше сенсу.

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

Отже, правило:

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

0

Я використовую статичні методи як для C ++, так і для C # для класів Utility, класів, які не мають жодних даних про екземпляри, лише один спосіб зібрати набір корисних споріднених методів.

int count1 = DBUtil::GetCountOfSlackerEmployees();
int count2 = DBUtil::GetCountOfEmployedSlackers();

0

Якщо припустити, що ви говорите про C ++ (ви не сказали), і ви маєте права (тобто не маю на увазі функції / методи членів):

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

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


0

Зазвичай вам потрібен статичний основний, щоб виступати в якості точки входу для вашої програми. Це може бути важливим.


0

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

Якщо ви постійно передаєте йому стан, це не є справді функцією без стану, ви просто робите функцію stateful з синтаксисом без стану. У цьому випадку він, ймовірно, належить об'єкту, що викликає, або, можливо, вказано рефакторинг для кращого вирівнювання стану та поведінки.


0

"чому б просто не замінити всі функції приватного члена на статичні функції?"

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


0

Смішно, як ніхто ще не зміг дати гарної відповіді. Я не впевнений, що і цей. Ви, напевно, повинні сприймати це як натяк на те, що їх слід використовувати якомога менше. Вони зрештою є процедурними, а не ООП.

Ось ще кілька прикладів:

У Obj-C, де їх називають методами класу, вони зазвичай використовуються як обгортки розподілу, де об'єкт поміщається в пул підрахунку посилань перед поверненням.

Інший приклад Obj-C - це зареєструвати новий клас у колекції класів. Скажімо, у вас є набір класів, кожен з яких обробляє один тип файлів. Коли ви створюєте новий клас для нового типу файлів, ви можете зареєструвати його у колекції (глобальній змінній), використовуючи статичний метод у класі, який визначає тип файлу.

У C ++ інше використання, про яке я можу подумати, - це м'яке виявлення помилок. Ваша функція конструктора не може вийти з ладу, за винятком випадків, коли викинете виняток. Ви можете встановити змінну екземпляра помилки, але це не завжди доречно. Натомість ви можете виконати частини, які можуть вийти з ладу в статичній обгортці, а потім виділити та повернути новий об’єкт або NULL при відмові.


0

Скажімо, ви хочете обчислити синус чогось.

Без статики:

Math math = new Math()
double y = math.sin(x)

Зі статичним:

double y = Math.sin(x)

Немає сенсу робити sinнестатичні. Він без громадянства і просто обробляє вхід.

Статичні функції не прив’язані до конкретного об’єкта. Вони є "загальними" функціями, які не залежать від внутрішнього стану об'єкта.


Статичні методи не "гарантовані без громадянства". Хоча це правда, що вони не можуть використовувати дані екземплярів, вони також мають доступ до деякого стану (а саме до статичних членів, як класу, до якого належить статичний метод, так і до іншого глобально видимого стану, наприклад статичних змінних інших класів).

@delnan: правда ... ти маєш рацію. Дозвольте зараз це виправити.
dagnelies

Без статичного: x.sin(). Ваша відповідь передбачає, що гріх повинен бути функцією "Математики", тоді як він явно діє на подвійному.
AjahnCharles

0

Тут як би пізно, але я хотів би спробувати створити точне визначення: статичні функції - це функції, які не можуть або не можуть посилатись на властивості / методи екземпляра класу, що містить.

У деяких мовах, як-от C #, у статичних класах можуть бути статичні поля або властивості, тому не зовсім правильно сказати, що вони не використовуються для стану; статична функція може використовувати статичний (глобальний) стан.

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

Допоміжні функції, як і математичні функції, є найчастішим прикладом, але є й інші.

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

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


0

Я хотів би зазначити ще одне використання статичного f ().

http://www.parashift.com/c++-faq/named-ctor-idiom.html

Зводиться до цього: staticфункції дозволяють створювати "Іменовані конструктори", тобто ви називаєте свою статичну функцію відповідною і самодокументуючою назвою, і ця статична функція викликає одного з конструкторів (оскільки конструктори мають однакові імена, і ви можете мати їх багато, їх важко розрізнити).

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