Niyə alıcılar və setters / accessors istifadə?

Bu dəyişənlər üçün açıq sahələrdən istifadə etmək əvəzinə yalnız getmək və qurmaq olan getters və setters istifadə üstünlük nədir?

Qəbul edənlər və ayarlayanlar heç bir zaman yalnız almaq / qurmaqdan daha çox şey etsələr, bunu çox tez anlaya bilərəm, ancaq 100% başa düşmürəm:

 public String foo; 

daha pis

 private String foo; public void setFoo(String foo) { this.foo = foo; } public String getFoo() { return foo; } 

Birincisi daha kiçik şablon kodunu qəbul edir.

1321
14 окт. Dek 14 ilə Dean J tərəfindən təyin olundu 2009-10-14 21:20 '09 da 21:20 'da, 2009-10-14 21:20
@ 38 cavab
  • 1
  • 2

Əslində, təsnifləşdirmə sübutundan başqa və gələcək dəyişikliklərin asanlaşdırılması ilə yanaşı, sinfi sahələrinin birbaşa xəritəsini yoxlamaq üçün aksessuarlardan istifadə etmək üçün çox yaxşı səbəblər var .

Budur bildiyim bəzi səbəblər:

  • Bir əmlakın alınması və ya qəbulu ilə əlaqəli davranışların kəşf edilməsi daha sonra əlavə funksiyalar (məsələn, doğrulama) əlavə etməyə imkan verir.
  • Alternativ nümayəndəlikdən istifadə edərək mülkiyyətə məruz qaldıqda əmlakın daxili təmsilçiliyini gizlətmək.
  • Açık arayüzünüzü değişikliğe ayırarak - ictimai interfeyinin sabit qalmasına imkan verir və mövcud müştərilərə təsir etmədən tətbiq dəyişir.
  • Həyatın və yaddaşın (idarə olunma) obyektin idarə olunmasının semantikasını idarə etmək - nəzarətsiz yaddaş (məsələn, C + + və ya Objective-C) olan mühitlərdə xüsusilə vacibdir.
  • Bir mülkün müəyyən bir dəyərə dəyişdirildiyi zaman və harada olduğu barədə diskussiya zamanı bəzi dillərdə olmadan qeyri-mümkün ola bilər.
  • Getter / seters atributları ilə işləmək üçün nəzərdə tutulmuş kitabxanalarla qarşılıqlı əlaqə - Mocking, Serialization və WPF, ağla gəlin.
  • Vərəsələrə bir obyektin davranışının semantikasını dəyişdirmək qabiliyyəti ilə təmin etmək və qeydə alıcı / müəyyən üsullara tabe olmaq
  • Getter / setter istifadə lambda ifadələr, dəyərlər kimi imkan verir.
  • Getters və seters müxtəlif səviyyələrdə çıxış imkanına malik ola bilər - məsələn, ictimaiyyətə açıq ola bilər, lakin dəsti qorunur.
807
14 окт. LBuşkin 14 okta cavab verdi . 2009-10-14 21:47 '09 at 9:47 PM 2009-10-14 21:47

2 həftə (ay, il) sayəsində, təyinatçınızın dəyərini təyin etməkdən daha çox şey etməsi lazım olduğunu başa düşdükdə, əmlakın 238 digər sinifdə birbaşa istifadə etdiyini başa düşəcəksiniz: -)

border=0
395
14 окт. Cavab ChssPly76 14 oktyabr verilir . 2009-10-14 21:23 '09 at 9:23 PM 2009-10-14 21:23

Açıq sahədə heç bir şey etməyən, sahəni geri qaytaran və ona verən bir cüt alıcıdan daha pis deyil. Birincisi, aydındır ki, (bir çox dillərdə) funksional fərqlər yoxdur. Hər hansı bir fərq, qoruma və ya okunabilirlik kimi digər faktorlarda olmalıdır.

Getter / setter cütünün tez-tez istifadə etdiyi üstünlük deyil. Tətbiqi dəyişə biləcəyiniz bir bəyanat var və müştəriləriniz yenidən yığılmamalıdır. Şübhəsiz, setterlər, belə doğruluq kimi xüsusiyyətləri əlavə etməyə imkan verir və müştəriləriniz hətta bu barədə bilmək məcburiyyətində deyillər. Lakin, təyinatçının bir çekini əvvəlki şərtlərə dəyişiklik etmək , əvvəlki müqavilənin pozulması olduqca sadədir: "Burada bir şeylər qoya bilərsən, sonra da alıcıdan eyni şeyi ala bilərsiniz."

Beləliklə, indi bir müqaviləni pozduğunuzda, codebase-də hər bir faylın dəyişdirilməsi etməlisiniz, qaçınmamalıdır. Bunun qarşısını alırsan, bütün kodun bu metodlar üçün müqavilənin fərqli olduğunu fərz edir.

Bu bir müqavilə olmasaydı, interfeys qəbuledilməz ölkələrdə obyektin yerləşdirilməsinə icazə verdi. İnkapsülasiyanın tam əksinə nədir. Bu sahənin həqiqətən başlanğıcdan heç bir şeyə uyğunlaşa bilməyəcəyi təqdirdə, niyə başdan gələn yoxlama yox idi?

Eyni arqument, bu passiv getter / setter cütlərinin digər algılanan üstünlükləri üçün tətbiq olunur: əgər daha sonra müəyyən edilmiş dəyəri dəyişdirməyi qərara alarsanız müqaviləni pozacaqsınız. Təmin olunmuş sinifdə default funksiyanı bir neçə zərərsiz dəyişikliklərdən (məsələn, journaling və ya digər müşahidə edilə bilən davranış kimi) fərqli olaraq əvəzləşdirdiyiniz halda, əsas sinif müqaviləsini pozur. Bu Lövsovun Əvəzləşdirmə prinsipinin pozulmasıdır və OO-nun prinsiplərindən biri hesab olunur.

Bir sinifdə hər bir sahə üçün bu dəhşətli güzgülər və setterlər varsa, bu, bir müqaviləsiz, bir invariant olmayan bir sinifdir. Həqiqətən obyektiv dizaynı varmı? Bütün siniflər bu alıcılara və settersə sahib olduqları halda, bu, sadəcə bir laqeyd məlumat sahibidir və səxavətli məlumat sahibləri sadə data sahibləri kimi görünməlidirlər:

313
24 авг. Cavab R. Martinho Fernandes 24 avqust tərəfindən verilir . 2012-08-24 13:55 '12 at 13:55 pm 2012-08-24 13:55

Bir çox insanlar getters və setters faydaları haqqında danışmaq, lakin mən şeytan müdafiəçisi oynamaq istəyirəm. Hal-hazırda programcıların bütün alıcıları və setterləri etmək qərarına gəldiyi çox böyük bir proqramı səhv hesab edirəm. Bu xoş görünə bilər, ancaq əks mühendislik ilə bir kabus.

Kodun yüzlərlə satırını gəzdiyinizi söyləyin və bununla qarşılaşın:

 person.name = "Joe"; 

Onun təyinatçısını anana qədər kodun bir parçası gözəldir. İndi bu yükləyiciyə əməl edirsiniz və ayrıca person.firstName, person.lastName, person.isHuman, person.hasReallyCommonFirstName və çağırır person.update () veritabanına sorğu və s. Oh, bu yerdəki yaddaş sızması meydana gəldi.

Yerli kod snippetini ilk baxışdan anlamaq yaxşı bir okunabilirlik xüsusiyyətidir. Ona görə də mən onları istifadə edərkən onlardan çəkinməyə çalışıram və istifadə etdikləri işləri minimuma endirirəm.

76
15 окт. Cavab Kai 15 oktyabr. 2009-10-15 00:00 '09 saat 00:00 'da

Təmiz obyektə yönəldilən dünyada alıcılar və setters dəhşətli bir anti-nümunəsidir . Bu yazı oxuyun: Getters / Setters. Evil Dövr Bir qayda olaraq, proqramçıları obyektlərin məlumat strukturları kimi düşünməyə təşviq edirlər və bu cür düşüncə tərzdə prosedurdur (məsələn, COBOL və ya C). Nesne yönümlü bir dildə məlumat strukturları yoxdur, ancaq davranışları ifşa edən obyektlər (xüsusiyyətlər deyildir!)

Onlar haqqında ətraflı məlumatı 3.5 bölməsində Elegant Objects (obyekt yönümlü proqramlaşdırma üzrə kitab) bölməsində tapa bilərsiniz.

45
23 сент. cavab yegor256 23 sentyabr verilir 2014-09-23 19:39 '14 at 19:39 2014-09-23 19:39

Bir çox səbəbi var. Sevdiyim davranışı dəyişdirmək və ya bir dəyişən üçün təyin edə bilərsiniz nə tənzimləmək lazımdır zaman. Məsələn, bir setSpeed ​​(int sürəti) üsulu olduğunu söyləək. Ancaq maksimum 100 sürətini təyin etmək istəyirsən. Belə bir şey edərdin:

 public void setSpeed(int speed) { if ( speed > 100 ) { this.speed = 100; } else { this.speed = speed; } } 

İndi kodunuzda HƏR YERƏ bir ictimai sahə istifadə edərsə və sonra yuxarıda göstərilən tələbə ehtiyacınız olduğunu başa düşsəydiniz? Yaxşı bir müvəffəqiyyətə nail olmaq üçün hər bir açıq sahəyə ovçuluq.

Mənim 2 qəpik :)

43
14 окт. Cavab 14 oktyabrda Peter D tərəfindən verilir . 2009-10-14 21:27 '09 9:27 pm 2009-10-14 21:27

Aksessuarlar və mutatorların üstünlüklərindən biri də çek etmək olar.

Məsələn, foo ictimaiyyətə açıq olsaydı, mən onu asanlıqla null olaraq təyin edə bilirdim və sonra kimsə başqası obyektin metodunu axtarmağa cəhd edə bilərdi. Ancaq o artıq deyil! setFoo metodu ilə setFoo foo heç vaxt null foo təyin olunmadığından əmin ola bilərəm.

Aksessuarlar və mutasiyalar həmçinin encapsulasiyaya imkan verir - yazdıqdan sonra qiyməti görmək lazım deyilsə (məsələn, bir konstruktorda quraşdırıldıqdan sonra metodlarla istifadə olunur, lakin heç vaxt dəyişdirilməməlidir) heç kim tərəfindən görülə bilməz. Amma digər siniflərin bunu görməsinə və ya dəyişdirməsinə icazə verə bilsəniz, uyğun aksesuar və / və ya mutator təmin edə bilərsiniz.

36
14 окт. Oktyabr 14-də Tomas Ouensə cavab verin 2009-10-14 21:25 '09 da 21:25 'də 2009-10-14 21:25

Dilinizə bağlıdır. Siz "Java" dan çox "obyekt yönümlü" olaraq qeyd etdiniz, buna görə də ChssPly76-a verilən cavab dilə bağlı olduğuna işarə etmək istərdim. Məsələn, Pythonda getters və setters istifadə etmək üçün heç bir səbəb yoxdur. Davranışı dəyişdirməlisinizsa, əsas atributu əldə etməklə getter və setteri bağlayan əmlakdan istifadə edə bilərsiniz. Belə bir şey:

 class Simple(object): def _get_value(self): return self._value -1 def _set_value(self, new_value): self._value = new_value + 1 def _del_value(self): self.old_values.append(self._value) del self._value value = property(_get_value, _set_value, _del_value) 
28
14 окт. jddyer cavab 14 Oct 2009-10-14 21:32 '09 da 9:32 'da 2009-10-14 21:32

Bəli, əlavə etmək istərdim ki, bəzən bəzən dəyişənlərin / obyektlərin təhlükəsizliyi və təhlükəsizliyi üçün zəruri olsa belə, biz real obyekt yönümlü bir proqramı kodlaşdırmaq istəyiriksə, onda biz AKSESSUARLARIN Xətalarını durdurmalıyıq , çünki bəzən biz onlara çox asılı olduqda bu, həqiqətən, lazım deyil və demək olar ki, biz dəyişənləri dərc edərkən.

23
22 авг. Jorge Aguilar tərəfindən verilmiş cavab 22 avqust 2012-08-22 17:47 '12 at 17:47 2012-08-22 17:47

Bunu bir azdan sonra bilirəm, amma performansla maraqlanan insanlar var deyə düşünürəm.

Bir az performans testi etdi. Mən "NumberHolder" adlı sinfi yazdım, bu, yaxşı bir tamsayıdır. anInstance.getNumber() metodundan və ya anInstance.number istifadə edərək anInstance.number birbaşa daxil olmaqla bu Tamsayı oxuya bilərsiniz. Proqramım hər iki istiqamətdə 1,000,000,000 dəfə oxuyur. Bu proses beş dəfə təkrarlanır və vaxt basılır. Aşağıdakı nəticəni aldım:

 Time 1: 953ms, Time 2: 741ms Time 1: 655ms, Time 2: 743ms Time 1: 656ms, Time 2: 634ms Time 1: 637ms, Time 2: 629ms Time 1: 633ms, Time 2: 625ms 

(Vaxt 1 düz yoldur, 2-ci dəfə bir alıcıdır)

Görürsən, alıcı (demək olar ki) hər zaman bir az daha sürətli olur. Daha sonra müxtəlif dövrələrlə çalışdım. 1 milyonun əvəzinə 10 milyon və 0,1 milyon istifadə etdim. Nəticələr:

10 milyon dövr:

 Time 1: 6382ms, Time 2: 6351ms Time 1: 6363ms, Time 2: 6351ms Time 1: 6350ms, Time 2: 6363ms Time 1: 6353ms, Time 2: 6357ms Time 1: 6348ms, Time 2: 6354ms 

10 milyon dövrə ilə, vaxt demək olar ki, eyni. Burada 100 min (0,1 milyon) dövr vardır:

 Time 1: 77ms, Time 2: 73ms Time 1: 94ms, Time 2: 65ms Time 1: 67ms, Time 2: 63ms Time 1: 65ms, Time 2: 65ms Time 1: 66ms, Time 2: 63ms 

Bundan başqa, müxtəlif dövrlər sayəsində, alıcı adi haldan bir qədər daha sürətli olur. Bu sizə kömək etdi ümid edirəm.

22
30 авг. Cavab kangalioo 30 avqust verilir . 2016-08-30 21:59 '16 saat 09:59 'da 2016-08-30 21:59

Təşəkkür edirəm, həqiqətən mənim düşüncəmə aydınlıq gətirdi. İndi burada (demək olar ki) 10 (demək olar ki) məcburiyyətli səbəblərdir.

  • Sizə sadəcə dəyər vermək və əldə etməkdən daha çox şey etmək lazım olduğunu başa düşdükdə, sadəcə birbaşa əldə etdiyiniz yeri dərhal sizə xəbər verəcək sahəni özəlləşdirə bilərsiniz.
  • Yaptığınız hər hansı bir test yalnız nadir hallarda praktikada olduğu kontekstər ola bilər.
  • Set dəyərini dəyişdirə bilərsiniz - bu, zəngin sizə [şok dəhşət] olaraq saxladığınız dəyəri göndərdiyi zaman bu mütləq bir kabusdur.
  • Daxili nümayəndəliyi gizlədə bilərsiniz - fantastik, buna görə bütün əməliyyatların simmetrik olduğuna əmin ola bilərsiniz?
  • Siz ümumi arayüzünüzü çatlardakı dəyişikliklərdən təcrid etdiniz - əgər interfeysi inkişaf etdirirsinizsə və bir şeyə birbaşa daxil olmağınızdan əmin idinizsə, onda siz layihələndirməyə davam etməli oldunuz.
  • Bəzi kitabxanalar bunu gözləyirlər, amma çox deyil - əksikliklər, serializasiya, səciyyəvi obyektlər ictimai sahələrlə bütün yaxşı işləyirlər.
  • Bu sinifə devralınca, siz default funksiyalarını qüvvədə saxlaya bilərsiniz - başqa sözlə, siz, həqiqətən, tətbiqləri gizlətməklə deyil, həm də uyğunsuz hala gətirənləri qarışdıra bilərsiniz.

Son üçü tərk edirəm (N / A və ya D / C) ...

21
27 марта '12 в 6:53 2012-03-27 06:53 Cavab 27 mart 2012-ci il tarixində saat 06:53 'da istifadəçi 595447 tərəfindən verilmişdir

Gələcəkdə bir çox şey, istehsal proqramları və sistemlərində dəyişiklik tələbini dəyişdirsə, gələcəkdə nə baş verəcəyini çox düşünməyin.

Lazım olduğunda sadə, asan, mürəkkəblik əlavə edin.

Mən biznes sahiblərinin cahilliyini dərin texniki biliklərdən istifadə etmək istəmirəm, çünki mən doğru olduğunu düşünürəm və ya yanaşmanı sevirəm.

Mənim mantığımın n icrasının yoxlanılması üçün yalnız modifikasiya edənlər və bəzi üsullarla getter ayarlayıcıları olmadan yazılmış bir kütləvi sistem var. Əgər tamamilə ehtiyac varsa. Bir şey istifadə edin.

15
14 июля '12 в 19:20 2012-07-14 19:20 Cavab 14 iyul, saat 12: 20- də Mohamed tərəfindən verilir

Mən uzun müddətdir ki, Java proqramı üçün bu barədə düşünürdüm və mən əsl səbəblərə inanıram:

  • Interface kodu, həyata keçirilmir
  • İnterfeys yalnız sahələri deyil, üsulları müəyyənləşdirir

Başqa sözlə, interfeysdə bir sahəni göstərməyin yeganə yolu yeni dəyər yazma metodunu və cari dəyəri oxumaq üsulunu təmin etməkdir.

Bu üsullar alçaldıcı alıcı və setterdir.

14
08 нояб. Cavab Thorbjørn Ravn Andersen tərəfindən verilir. 2009-11-08 00:55 '09 at 0:55 2009-11-08 00:55

Getters və setters istifadə:

  • təkrar istifadə etmək üçün
  • Proqramlaşdırmanın sonrakı mərhələlərində yoxlanılması üçün

Getter və setter üsulları bir sinifin xüsusi üzvlərinə çatmaq üçün ictimai interfeyslərdir.


Mantrasiya Kapsülleme

Kapsülləşdirmə mandatı özəl və ictimai sahələri etməkdir.

Getter Yöntemleri: Özel değişkenlere erişebiliriz.

Setter üsulları: Şəxsi sahələri dəyişə bilərik.

Getter və setter metodları yeni funksiyalar əlavə etmir, baxmayaraq ki, bu üsulu daha sonra dəyişə bilərik

  • daha yaxşı
  • daha təhlükəsizdir; və
  • daha sürətli

Hər iki halda, bu dəyəri qaytarır bir dəyər istifadə edə bilərsiniz. Bunun əvəzinə:

 int x = 1000 - 500 

istifadə

 int x = 1000 - class_name.getValue(); 

Bir layman baxımından

2019

14
02 сент. Devrath Sep 02'ye cavab verin 2013-09-02 09:51 '13 at 9:51 2013-09-02 09:51

Bu tənbəl yükləmə üçün faydalı ola bilər. Sözü gedən obyektin bir verilənlər bazasında saxlandığını bildirin və ehtiyacınız olmadıqda onu qəbul etmək istəmirik. Nesne alıcı tərəfindən alındıqda, birincisi, birinin istəmədiyi qədər, daxili obyekt null ola bilər, sonra alıcıyı ilk zəng etdiyiniz zaman qəbul edə bilərsiniz.

Bir neçə müxtəlif veb xidmət çağırışlarından bəzi məlumatları yükləyən mənə verilmiş bir proyektdə bir əsas səhifə sinfi var idi, lakin bu veb xidmət zənglərindəki məlumatlar həmişə bütün uşaq səhifələrində istifadə edilməmişdir. Web xidmətləri, bütün faydalar üçün, yeni təriflərin qabaqcıllarıdır "yavaş", buna ehtiyac yoxdur, əgər bir web xidmət zəng etmək istəmirsiniz.

Mən ictimai sahələrdən getterlərə köçdüm və indi getters önbelleği yoxlayır və veb xidmətini çağırmazsa. Beləliklə, kiçik qablaşdırma ilə, bir çox veb xidmət çağırışı qarşısı alındı.

Beləliklə, alıcı məni hər bir uşaq səhifəsinə lazım olanı anlamaq üçün çalışır. Mənə lazım olsa, mən alıcıya zəng vururam və hələlik yoxdursa mənim üçün tapmağı istəyir.

  protected YourType _yourName = null; public YourType YourName{ get { if (_yourName == null) { _yourName = new YourType(); return _yourName; } } } 
14
14 окт. cavab 14 aylıq bir qəzetə verilir . 2009-10-14 22:08 '09 at 10:08 pm 2009-10-14 22:08

Cavablarda buraxdığım bir cəhət, giriş xüsusiyyətidir:

  • Üzvləriniz üçün yalnız konfiqurasiya və əldə etmək üçün bir çıxış xüsusiyyətiniz var
  • setters və getters üçün onu konfiqurasiya edə və ayrıca müəyyən edə bilərsiniz.
12
14 окт. cavab 14 oktyabr cümə günü verilir . 2009-10-14 21:38 '09 at 9:38 PM 2009-10-14 21:38

"Xassələri" (C + +, Java) dəstəkləməyən dillərdə və ya xüsusiyyətləri (C #) dəyişən zaman müştərilərin kompilyasiya edilməsini tələb etməsi üçün, get / set üsullarının istifadəsi daha asandır. Məsələn, setFoo metoduna doğrulama məntiqini əlavə etmək sinfi ictimai interfeysini dəyişdirməyi tələb etmir.

"Real" xassələri dəstəkləyən dillərdə (Python, Ruby, bəlkə Smalltalk?), Metodları almaq və / yoxlamaq üçün heç bir əhəmiyyəti yoxdur.

10
14 окт. John Millikin tərəfindən 14 oktyabrda cavab verdi 2009-10-14 21:25 '09 da 21:25 'də 2009-10-14 21:25

EDIT: Mən bu suala cavab vermişəm, çünki proqramı öyrənən, soruşan bir çox insan var və cavabların əksəriyyəti çox texniki cəhətdən səlahiyyətlidir, ancaq bir başlanğıc olduğunuzu başa düşmək asan deyil. Biz hamısı yeni idi, buna görə də əlimə dost cavab verəcəyimi düşündüm.

İki əsas olan polimorfizm və qiymətləndirmədir. Yalnız bir sadə data quruluşu olsa belə.

Gəlin bu sadə sinfi var:

 public class Bottle { public int amountOfWaterMl; public int capacityMl; } 

Çox sadə sinif, onun içində maye miqdarını və onun tutumunu (mililitlərlə) olan ehtiva edir.

Bunu edərkən nə baş verir?

 Bottle bot = new Bottle(); bot.amountOfWaterMl = 1500; bot.capacity = 1000; 

Yaxşı, işləməyini gözləmirdin, doğru? Orada bəzi sağlamlıq testi istəyirsən. Və ən pis nədir, əgər heç vaxt maksimum gücü göstərməmişəm? Sevgilim, problemimiz var.

Ancaq başqa bir problem var. Şüşə yalnız bir növ konteyner olarsa? Что, если бы у нас было несколько контейнеров, все с емкостью и количеством заполненной жидкости? Если бы мы могли просто создать интерфейс, мы могли бы позволить остальной части нашей программы принять этот интерфейс, а бутылки, канистры и всякие вещи просто работали бы взаимозаменяемо. Разве это не было бы лучше? Поскольку интерфейсы требуют методов, это тоже хорошо.

Мы получим что-то вроде:

 public interface LiquidContainer { public int getAmountMl(); public void setAmountMl(int amountMl); public int getCapacityMl(); public void setCapcityMl(int capacityMl); } 

Böyüklər! И теперь мы просто меняем бутылку на это:

 public class Bottle extends LiquidContainer { private int capacityMl; private int amountFilledMl; public Bottle(int capacityMl, int amountFilledMl) { this.capacityMl = capacityMl; this.amountFilledMl = amountFilledMl; checkNotOverFlow(); } public int getAmountMl() { return amountFilledMl; } public void setAmountMl(int amountMl) { this.amountFilled = amountMl; checkNotOverFlow(); } public int getCapacityMl() { return capacityMl; public void setCapcityMl(int capacityMl) { this.capacityMl = capacityMl; checkNotOverFlow(); } private void checkNotOverFlow() { if(amountOfWaterMl > capacityMl) { throw new BottleOverflowException(); } } 

Я оставлю определение BottleOverflowException в качестве упражнения для читателя.

Теперь обратите внимание, насколько это более устойчиво. Теперь мы можем иметь дело с контейнером любого типа в нашем коде, принимая LiquidContainer вместо Bottle. И как эти бутылки справляются с такими вещами, все могут различаться. У вас могут быть бутылки, которые записывают свое состояние на диск, когда они меняются, или бутылки, которые сохраняются в базах данных SQL, или GNU знает, что еще.

И все это может иметь разные способы обработки различных криков. Бутылка просто проверяет, и если она переполняет его, это исключает RuntimeException. Но это может быть неправильным. (Существует полезное обсуждение, которое нужно обсудить с обработкой ошибок, но я делаю это очень просто здесь специально. Люди в комментариях, скорее всего, укажут на недостатки этого упрощенного подхода.))

И да, похоже, мы переходим от очень простой идеи к быстрому получению гораздо лучших @.

Там также третье, что не все обратились: Getters и seters используют вызовы методов. Это означает, что они выглядят как обычные методы везде. Вместо того, чтобы иметь странный специфический синтаксис для DTO и прочее, вы везде одинаковы.

9
29 нояб. Haakon Lotveit tərəfindən verilmiş cavab noyabrın 29-da '15 в 17:37 2015-11-29 17:37

Один из основных принципов проектирования OO: Инкапсуляция!

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

6
ответ дан Justin Niessner 14 окт. '09 в 21:25 2009-10-14 21:25

С точки зрения объектной ориентации обе альтернативы могут повредить поддержанию кода, ослабляя инкапсуляцию классов. Для обсуждения вы можете изучить эту замечательную статью: http://typicalprogrammer.com/?p=23

4
ответ дан andrers52 30 апр. '12 в 21:57 2012-04-30 21:57

Вы должны использовать геттеры и сеттеры, когда:

  • Вы имеете дело с чем-то, что является концептуально атрибутом, но:
    • У вашего языка нет свойств (или какого-либо подобного механизма, например, трассировки переменных Tcl) или
    • Для этого варианта использования недостаточно поддержки языковой поддержки или
    • Идиоматические соглашения вашего языка (или иногда ваши рамки) поощряют геттеры или сеттеры для этого варианта использования.

Итак, это очень редко общий вопрос ОО; это вопрос, специфичный для языка, с различными ответами на разные языки (и различные варианты использования).


С точки зрения теории ОО геттеры и сеттеры бесполезны. Интерфейс вашего класса - это то, что он делает, а не то, что его состояние. (Если нет, вы написали неправильный класс.) В очень простых случаях, когда то, что делает класс, просто, например, представляет точку в прямоугольных координатах, * атрибуты являются частью интерфейса; геттеры и сеттеры просто облака, что. Но во всех, кроме очень простых случаях, ни атрибуты, ни геттеры, ни сеттеры не являются частью интерфейса.

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

* Даже для этого простого класса вы можете не обязательно указывать значения x и y . Если это действительно класс, не должны ли он иметь такие методы, как translate , rotate и т.д.? Если это только класс, потому что у вашего языка нет записей /structs/named tuples, то на самом деле это не вопрос OO...


Но никто никогда не делает общий дизайн OO. Они выполняют дизайн и реализацию на определенном языке. И на некоторых языках геттеры и сеттеры далеки от бесполезности.

Если ваш язык не имеет свойств, то единственный способ представить что-то, что концептуально является атрибутом, но на самом деле вычисляется, или проверяется, и т.д., происходит через getters и seters.

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

Что касается "что, если я хочу позже изменить свою реализацию?" вопрос (который повторяется несколько раз в разных формулировках как в вопросе OP, так и в принятом ответе): если это действительно чистое изменение реализации, и вы начали с атрибута, вы можете изменить его на свойство без влияния на интерфейс. Если, конечно, ваш язык не поддерживает это. Так что это действительно тот же случай снова.

Также важно следить за идиомами языка (или рамки), который вы используете. Если вы напишете красивый код стиля Ruby на С#, любой опытный разработчик С#, отличный от вас, будет иметь проблемы с его чтением, и это плохо. Некоторые языки имеют более сильные культуры вокруг своих соглашений, чем другие. - И не может быть совпадением, что Java и Python, которые находятся на противоположных концах спектра для того, как идиоматические геттеры, имеют две из самых сильных культур.

Помимо человеческих читателей, будут библиотеки и инструменты, которые ожидают, что вы будете следовать конвенциям и сделайте свою жизнь более сложной, если вы этого не сделаете. Виджеты Builder Interface Builder для чего-либо, кроме свойств ObjC, или с использованием некоторых Java-mocking-библиотек без геттеров, просто усложняют вашу жизнь. Если инструменты важны для вас, не сражайтесь с ними.

4
ответ дан abarnert 19 авг. '14 в 7:47 2014-08-19 07:47

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

Есть несколько преимуществ использования методов getter и setter, таких как возможность создавать элементы со сложными функциональными возможностями, к которым вы можете получить доступ, например, к свойствам. Они также позволяют создавать свойства только для чтения и только для записи.

Несмотря на то, что методы getter и setter полезны, вы должны быть осторожны, чтобы не злоупотреблять ими, потому что, помимо прочих проблем, они могут затруднить обслуживание кода в определенных ситуациях. Кроме того, они предоставляют доступ к вашей реализации класса, например, к публичным пользователям. Практика ООП препятствует прямому доступу к свойствам внутри класса.

Когда вы пишете классы, вам всегда рекомендуется делать как можно больше ваших переменных экземпляра частным и соответственно добавлять методы getter и setter. Это происходит потому, что есть несколько раз, когда вы не можете позволить пользователям изменять определенные переменные в ваших классах. Например, если у вас есть частный статический метод, который отслеживает количество экземпляров, созданных для определенного класса, вы не хотите, чтобы пользователь модифицировал этот счетчик с помощью кода. Только инструкция конструктора должна увеличивать эту переменную всякий раз, когда она вызывает. В этой ситуации вы можете создать переменную частного экземпляра и разрешить метод getter только для переменной счетчика, что означает, что пользователи могут извлекать текущее значение только с помощью метода getter, и они не смогут устанавливать новые значения используя метод setter. Создание геттера без сеттера - это простой способ сделать определенные переменные в вашем классе доступными только для чтения.

3
ответ дан Sumit Singh 30 авг. '12 в 16:02 2012-08-30 16:02

Есть веская причина, чтобы рассмотреть возможность использования accessors - нет наследования свойств. Aşağıdakı nümunəyə baxın:

 public class TestPropertyOverride { public static class A { public int i = 0; public void add() { i++; } public int getI() { return i; } } public static class B extends A { public int i = 2; @Override public void add() { i = i + 2; } @Override public int getI() { return i; } } public static void main(String[] args) { A a = new B(); System.out.println(ai); a.add(); System.out.println(ai); System.out.println(a.getI()); } } 

Nəticə:

 0 0 4 
3
ответ дан GeZo 13 мая '14 в 12:47 2014-05-13 12:47

Код развивается. private отлично подходит для защиты данных. В конце концов все классы должны быть своего рода "минипрограммами", которые имеют четко определенный интерфейс, который вы не можете просто вставлять с внутренними элементами.

Тем не менее, разработка программного обеспечения заключается не в том, чтобы установить эту окончательную версию класса, как если бы вы нажимали какую-то чугунную статую с первой попытки. Пока вы работаете с ним, код больше похож на глину. Он развивается , когда вы его разрабатываете и узнаете больше о проблемном домене, который вы решаете. Во время разработки классы могут взаимодействовать друг с другом, чем они должны (зависимость, которую вы планируете учитывать), сливаться или разделиться. Поэтому я думаю, что дискуссия сводится к людям, которые не хотят религиозно писать

 int getVar() const { return var ; } 

Beləliklə, siz:

 doSomething( obj->getVar() ) ; 

Bunun əvəzinə

 doSomething( obj->var ) ; 

Не только getVar() визуально шумно, он дает иллюзию, что gettingVar() является каким-то более сложным процессом, чем он есть на самом деле. Как вы (как писатель класса) относитесь к святости var , особенно сбивает с толку пользователь вашего класса, если у него есть сеттер паушру - тогда похоже, что вы пытаетесь заставить эти ворота "защищать" то, что вы настаиваете (святость var ), но даже вы соглашаетесь с тем, что защита не стоит того, чтобы кто-либо мог просто войти и set var к любой ценности, которую они хотят, без вас глядя на то, что они делают.

Итак, я программирую следующим образом (предполагая подход типа "подвижный" - т.е. когда я пишу код, не зная точно, что он будет делать/не имеет времени или опыта для планирования сложного набора интерфейсов стиля водопада):

1) Начните со всех открытых элементов для базовых объектов с данными и поведением. Вот почему во всем моем "примерном" коде С++ вы заметите, что я использую struct вместо class всюду.

2) Когда внутреннее поведение объекта для элемента данных становится достаточно сложным (например, ему нравится поддерживать внутренний std::list в некотором порядке), записываются функции типа доступа. Поскольку я программирую сам по себе, я не всегда устанавливаю член private сразу, но где-то по эволюции класса член будет "продвигаться" на protected или private .

3) Классы, которые полностью сформированы и имеют строгие правила относительно их внутренних элементов (т.е. они точно знают, что они делают, и вы не должны "трахаться" (технический термин) со своими внутренностями) даны class назначение, закрытые члены по умолчанию, и только избранным нескольким членам разрешено быть public .

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

3
ответ дан bobobobo 05 мая '13 в 5:07 2013-05-05 05:07

Другое использование (на языках, поддерживающих свойства) заключается в том, что сеттеры и геттеры могут подразумевать, что операция нетривиальна. Как правило, вы хотите избегать делать что-либо, что вычислительно дорогостоящее в свойстве.

2
ответ дан Jason Baker 14 окт. '09 в 21:27 2009-10-14 21:27

В объектно-ориентированном языке методы и их модификаторы доступа объявляют интерфейс для этого объекта. Между конструктором и методами доступа и мутатора разработчик может контролировать доступ к внутреннему состоянию объекта. Если переменные просто объявлены публичными, тогда нет способа регулировать этот доступ. И когда мы используем сеттеры, мы можем ограничить пользователя необходимым для ввода. Средство подачи для этой очень переменной будет проходить через правильный канал, и канал предопределен нами. Так что безопаснее использовать сеттеры.

2
ответ дан Antz 14 окт. '09 в 23:01 2009-10-14 23:01

Одним из относительно современных преимуществ getters/seters является то, что упрощает просмотр кода в тегированных (индексированных) редакторах кода. Məsələn, Если вы хотите узнать, кто устанавливает член, вы можете открыть иерархию вызовов сеттера.

С другой стороны, если член является общедоступным, инструменты не позволяют фильтровать доступ для чтения/записи к члену. Таким образом, вы должны тащиться, несмотря на все использования члена.

2
ответ дан Rakesh Singh 03 янв. '17 в 19:10 2017-01-03 19:10

Getters и настройки используются для реализации двух основных аспектов объектно-ориентированного программирования:

  • Абстракция
  • Герметизация

Предположим, что у нас есть класс Employee:

 package com.highmark.productConfig.types; public class Employee { private String firstName; private String middleName; private String lastName; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getMiddleName() { return middleName; } public void setMiddleName(String middleName) { this.middleName = middleName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getFullName(){ return this.getFirstName() + this.getMiddleName() + this.getLastName(); } } 

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

2
ответ дан Pritam Banerjee 10 дек. '15 в 23:44 2015-12-10 23:44

Я хотел бы просто бросить идею аннотации: @getter и @setter. С помощью @getter вы должны иметь возможность obj = class.field, но не class.field = obj. С @setter, наоборот. С @getter и @setter вы должны быть в состоянии сделать то и другое. Это позволит сохранить инкапсуляцию и сократить время, не вызывая тривиальные методы во время выполнения.

1
ответ дан fastcodejava 15 окт. '09 в 1:40 2009-10-15 01:40

Кроме того, это означает "будущий" класс. В частности, переход с поля на свойство - это разрыв ABI, поэтому, если вы позже решите, что вам нужна больше логики, чем просто "установить/получить поле", тогда вам нужно сломать ABI, что, конечно, создает проблемы для чего-либо else уже скомпилирован против вашего класса.

1
ответ дан Pete 14 окт. '09 в 21:25 2009-10-14 21:25
  • 1
  • 2

Другие вопросы по меткам или Задайте вопрос