Kiedy używać zmiennej instancji obiektu, a kiedy przekazywać argument do metody

93

Jak zdecydujesz między przekazywaniem argumentów do metody a zwykłym deklarowaniem ich jako zmiennych instancji obiektu, które są widoczne dla wszystkich metod obiektu?

Wolę przechowywać zmienne instancji na liście na końcu klasy, ale lista ta wydłuża się wraz z rozwojem mojego programu. Wydaje mi się, że jeśli zmienna jest przekazywana wystarczająco często, powinna być widoczna dla wszystkich metod, które jej potrzebują, ale potem zastanawiam się, „jeśli wszystko jest publiczne, nie będzie w ogóle potrzeby przekazywania czegokolwiek!”.

Ziggy
źródło
1
Jeśli masz konkretne przykłady, możesz uzyskać bardziej bezpośrednio przydatne odpowiedzi
brabster,

Odpowiedzi:

55

Ponieważ odnosisz się do zmiennych instancji, zakładam, że pracujesz w języku zorientowanym obiektowo. Do pewnego stopnia to, kiedy używać zmiennych instancji, jak definiować ich zakres i kiedy używać zmiennych lokalnych, jest subiektywne, ale istnieje kilka praktycznych zasad, których można przestrzegać podczas tworzenia klas.

  • Zmienne instancji są zwykle uważane za atrybuty klasy. Pomyśl o nich jak o przymiotnikach przedmiotu, który zostanie utworzony z twojej klasy. Jeśli dane Twojej instancji mogą pomóc w opisaniu obiektu, prawdopodobnie można założyć, że jest to dobry wybór na przykład dane.

  • Zmienne lokalne są używane w ramach metod, aby pomóc im w zakończeniu pracy. Zwykle celem metody powinno być uzyskanie pewnych danych, zwrócenie niektórych danych i / lub przetworzenie / uruchomienie algorytmu na niektórych danych. Czasami warto pomyśleć o zmiennych lokalnych jako o sposobach pomagania metodzie w przejściu od początku do końca.

  • Zakres zmiennej instancji służy nie tylko do zapewnienia bezpieczeństwa, ale także do hermetyzacji. Nie zakładaj, że „celem powinno być zachowanie prywatności wszystkich zmiennych”. W przypadku dziedziczenia zwykle dobrą alternatywą jest oznaczanie zmiennych jako chronionych. Zamiast oznaczać wszystkie dane instancji jako publiczne, tworzysz metody pobierające / ustawiające dla tych, które muszą mieć dostęp do świata zewnętrznego. Nie udostępniaj ich wszystkich - tylko te, których potrzebujesz. Nastąpi to przez cały cykl rozwoju - trudno to odgadnąć od samego początku.

Jeśli chodzi o przekazywanie danych po klasie, trudno jest powiedzieć, że to, co robisz, jest dobrą praktyką bez zobaczenia kodu. Czasami działanie bezpośrednio na danych instancji jest w porządku; innym razem tak nie jest. Moim zdaniem jest to coś, co wiąże się z doświadczeniem - wraz z poprawą umiejętności myślenia obiektowego rozwiniesz intuicję.

Tomek
źródło
Moją odpowiedzią byłoby dodanie tej odpowiedzi do odpowiedzi H-Man2 (całe życie). Powinien być atrybutem składowym wtedy i tylko wtedy, gdy jest to trwały stan obiektu. Oznacza to, że wartość sama w sobie ma sens poza zakresem bieżącego stosu metod.
David Rodríguez - dribeas
1
Moja instynktowna reakcja to zgodzić się z Davidem i H-MAn2. Jednak czytam „czysty kod” Roberta c Martina, aw rozdziale 3 refaktoryzuje kod, aby przenieść coś z parametru metody do zmiennej składowej, ponieważ posiadanie wielu parametrów jest złe. Podsumowując, wydaje mi się, że jeśli twoja klasa ma tylko jedną odpowiedzialność, to czas życia obiektu jest taki sam jak czas życia tego obliczenia, więc może rzeczywista odpowiedź brzmi, że jeśli musisz zadać to pytanie, twoja klasa jest zbyt duża?
Andy
@ DavidRodríguez-dribeas co masz na myśli mówiąc o stosie metod?
popełnionyandroider
@committedandroider: jeśli wartość przeżyje bieżące wywołanie funkcji
David Rodríguez - dribeas
46

Zależy to głównie od czasu życia danych przechowywanych w zmiennej. Jeśli dane są używane tylko podczas obliczeń, przekaż je jako parametr. Jeśli dane są powiązane z okresem istnienia obiektu, użyj zmiennej instancji.

Gdy lista zmiennych staje się zbyt długa, może warto pomyśleć o refaktoryzacji niektórych części klasy do nowej klasy.

H-Man2
źródło
21

Moim zdaniem zmienne instancji są potrzebne tylko wtedy, gdy dane będą używane w różnych połączeniach.

Oto przykład:

myCircle = myDrawing.drawCircle(center, radius);

Teraz obrazowanie klasy myDrawing wykorzystuje 15 funkcji pomocniczych do tworzenia obiektu myCircle, a każda z tych funkcji będzie potrzebować środka i promienia. Nadal nie powinny być ustawiane jako zmienne instancji klasy myDrawing. Ponieważ już nigdy nie będą potrzebne.

Z drugiej strony klasa myCircle będzie musiała przechowywać zarówno środek, jak i promień jako zmienne instancji.

myCircle.move(newCenter);
myCircle.resize(newRadius);

Aby obiekt myCircle wiedział, jaki jest jego promień i środek w momencie wykonywania tych nowych wywołań, muszą one być przechowywane jako zmienne instancji, a nie tylko przekazywane do funkcji, które ich potrzebują.

Zasadniczo zmienne instancji są więc sposobem na zapisanie „stanu” obiektu. Jeśli zmienna nie jest konieczna do poznania stanu obiektu, to nie powinna być zmienną instancji.

A jeśli chodzi o upublicznianie wszystkiego. W tej chwili może to ułatwić ci życie. Ale wróci, by cię prześladować. Proszę nie.

ng.mangine
źródło
Możesz po prostu zdefiniować ruch, aby użyć parametrów (oldCenter, newCenter).
obesechicken 13
4

MOIM ZDANIEM:

Jeśli zmienna stanowi część stanu instancji, powinna to być zmienna instancji - classinstance HAS-A instancevariable.

Gdybym odkrył, że wielokrotnie przekazuję coś do metod instancji lub stwierdziłem, że mam dużą liczbę zmiennych instancji, prawdopodobnie spróbuję spojrzeć na mój projekt na wypadek, gdyby coś przeoczyłem lub gdzieś wykonałem złą abstrakcję.

Mam nadzieję, że to pomoże

brabster
źródło
3

Oczywiście łatwo jest zachować jedną dużą listę zmiennych publicznych w klasie. Ale nawet intuicyjnie można stwierdzić, że nie jest to właściwa droga.

Zdefiniuj każdą zmienną tuż przed jej użyciem. Jeśli zmienna obsługuje funkcję określonej metody, używaj jej tylko w zakresie tej metody.

Pomyśl także o bezpieczeństwie, publiczna zmienna klasy jest podatna na niepożądane zmiany z „zewnętrznego” kodu. Twoim głównym celem powinno być zachowanie prywatności wszystkich zmiennych, a każda zmienna, która nie jest, powinna mieć ku temu bardzo dobry powód.

Jeśli chodzi o przekazywanie parametrów przez całą górę stosu, może to bardzo szybko stać się brzydkie. Praktyczną zasadą jest zachowanie czystości i elegancji sygnatur metod. Jeśli widzisz wiele metod korzystających z tych samych danych, zdecyduj, czy wystarczająco ważne jest, aby być członkiem klasy, a jeśli nie, zrefaktoryzuj kod, aby miał więcej sensu.

Sprowadza się do zdrowego rozsądku. Zastanów się dokładnie, gdzie i dlaczego deklarujesz każdą nową zmienną, jaka powinna być jej funkcja, a następnie podejmij decyzję, w jakim zakresie ma ona żyć.

Yuval Adam
źródło
Często chcesz, aby metody były publiczne, więc możesz je przetestować.
obesechicken 13