Najlepsza praktyka tworzenia instancji nowego fragmentu Androida


706

Widziałem dwie ogólne praktyki tworzenia nowego fragmentu w aplikacji:

Fragment newFragment = new MyFragment();

i

Fragment newFragment = MyFragment.newInstance();

Druga opcja wykorzystuje metodę statyczną newInstance()i ogólnie zawiera następującą metodę.

public static Fragment newInstance() 
{
    MyFragment myFragment = new MyFragment();
    return myFragment;
}

Na początku myślałem, że główną korzyścią jest to, że mogę przeciążać metodę newInstance (), aby zapewnić elastyczność podczas tworzenia nowych instancji Fragmentu - ale mogę to również zrobić, tworząc przeciążony konstruktor Fragmentu.

Przegapiłem coś?

Jakie są zalety jednego podejścia względem drugiego? Czy to tylko dobra praktyka?


Kiedy są parametry, nie ma wyboru, na co tutaj szeroko odpowiada. Pozostaje jednak pytanie o konstrukcję tego fragmentu bez argumentów.
rds

1
Po zapoznaniu się z wzorcami fabrycznymi i tym, jak klasa wywołująca, która nie tworzyła samego obiektu, pomaga je oddzielić, pomyślałem, że będzie to mocna strona metody newInstance (). Czy się mylę? Nie widziałem tego konkretnego argumentu jako korzyści.
Aplikacje mobilne,

Odpowiedzi:


1136

Jeśli Android zdecyduje się później odtworzyć Fragment, wywoła konstruktor fragmentu bez argumentu. Przeciążenie konstruktora nie jest rozwiązaniem.

Biorąc to pod uwagę, sposobem przekazywania rzeczy do Fragmentu, aby były one dostępne po odtworzeniu Fragmentu przez Androida, jest przekazanie pakietu do setArgumentsmetody.

Na przykład, jeśli chcielibyśmy przekazać liczbę całkowitą do fragmentu, użylibyśmy czegoś takiego:

public static MyFragment newInstance(int someInt) {
    MyFragment myFragment = new MyFragment();

    Bundle args = new Bundle();
    args.putInt("someInt", someInt);
    myFragment.setArguments(args);

    return myFragment;
}

Później we fragmencie onCreate()możesz uzyskać dostęp do tej liczby całkowitej, używając:

getArguments().getInt("someInt", 0);

Ten pakiet będzie dostępny, nawet jeśli fragment zostanie w jakiś sposób odtworzony przez system Android.

Uwaga: setArgumentsmożna wywołać tylko przed dołączeniem fragmentu do działania.

To podejście jest również udokumentowane w odnośniku dla programistów Androida: https://developer.android.com/reference/android/app/Fragment.html


7
@Vlasto niestety nie można zastąpić metod statycznych.
AJD

8
@yydl Myślę, że coś tu brakuje, czy i tak nie mógłbyś użyć tutaj konstruktora, który tworzy pakiet i wywołuje setArguments (), ponieważ będzie on wywoływany tylko przez Twój kod (a nie, gdy Android ponownie utworzy twój fragment)?
Mike Tunnicliffe

9
@mgibson Państwo musi wykorzystać pakiet jeśli chcesz dane mają być dostępne, gdy fragment później odtworzone.
yydl

114
WYMUSZENIE do stworzenia konstruktora bez argumentów dla fragmentów jest potencjalnie największą gotówką we wszystkich programach, gdziekolwiek. Wymusza to całkowitą zmianę paradygmatu w tworzeniu i inicjowaniu obiektów. Jeśli jesteś nowym użytkownikiem Androida i napotkałeś ten wątek, przeczytaj tę odpowiedź w kółko.
rmirabelle,

9
Kłóciłbym się z tym twierdzeniem. Po pierwsze, bezpieczeństwo typu jest kwestią językową, a nie ramową. Po drugie, IMO, struktura wkracza w obszar „rzeczy, których interfejs API nigdy nie powinien robić”. Jeśli chcę przekazać bibliotekę kongresową do mojego konstruktora fragmentów, powinienem mieć taką możliwość. Kontrakt konstruktora „bez argumentów” zasadniczo zabija stosowanie wstrzykiwania zależności we fragmentach - wielkie fuj.
rmirabelle

95

Jedyne korzyści z korzystania z newInstance()tego, co widzę, są następujące:

  1. Będziesz miał jedno miejsce, w którym wszystkie argumenty użyte przez fragment mogą być spakowane i nie musisz pisać kodu poniżej za każdym razem, gdy utworzysz fragment.

    Bundle args = new Bundle();
    args.putInt("someInt", someInt);
    args.putString("someString", someString);
    // Put any other arguments
    myFragment.setArguments(args);
  2. Jest to dobry sposób, aby powiedzieć innym klasom, jakich argumentów oczekuje wiernie działać (chociaż powinieneś być w stanie obsługiwać przypadki, jeśli w instancji fragmentu nie ma żadnego argumentu).

Uważam więc, że newInstance()dobrym pomysłem jest użycie elementu statycznego do utworzenia fragmentu.


4
1) Czym to się różni od umieszczenia logiki w konstruktorze? Oba są pojedynczymi miejscami, w których uwzględniono tę logikę. 2) W jaki sposób parametry w fabryce statycznej różnią się od parametrów w konstruktorze? Oba mówią, jakich argumentów należy się spodziewać. Chodzi mi o to, że jest to inny paradygmat, jasne, ale nie ma wyraźnej korzyści z tego nad używaniem konstruktorów.
RJ Cuthbertson,

2
Nie można używać niestandardowych konstruktorów dla fragmentu. Framework używa konstruktora no argument do przywracania fragmentów.
500865,

5
Tak, zgadzam się z tobą. Mówię koncepcyjnie, że nie ma korzyści z używania statycznego wzorca fabrycznego zamiast używania przeciążonych konstruktorów i odwrotnie. Oba twoje punkty są ważne w obu wzorach; nie ma żadnej korzyści z używania jednego nad drugim. Android zmusza cię do korzystania ze statycznego wzorca fabrycznego - ale nie ma żadnej korzyści z używania jednego lub drugiego.
RJ Cuthbertson,

pastebin.com/EYJzES0j
RJ Cuthbertson

@RJCuthbertson Możliwą korzyścią byłaby możliwość tworzenia i zwracania podklas klasy statycznej metody fabrycznej, tj. Zwracania odpowiedniej podklasy dla danej sytuacji.
urgentx

62

Jest też inny sposób:

Fragment.instantiate(context, MyFragment.class.getName(), myBundle)

Jeśli się nie mylę, jest to możliwe tylko wtedy, gdy korzystasz z biblioteki wsparcia Androida.
Timo,

2
Próbowałem tego z biblioteką pomocniczą, ale w onCreateView (w moim fragmencie) przekazany pakiet był pusty, więc wybrałem opcję setArguments / getArguments i zadziałało (dla każdego, kto to czyta).
Jrop

1
Co ciekawe, nigdy wcześniej nie widziałem takiego podejścia. Czy ma to jakąś przewagę nad innymi metodami tworzenia fragmentu?
IgorGanapolsky

22
Z dokumentacji dla programistów ,instantiate() Creates a new instance of a Fragment with the given class name. This is the same as calling its empty constructor.
Brian Bowman,

2
Chociaż wspomniano to samo, co nazywając pustego konstruktora. „args.setClassLoader (f.getClass (). getClassLoader ());” nazywa się poniżej argumentami pakietu
Gökhan Barış Aker

49

Podczas gdy @yydl daje przekonujący powód, dla którego newInstancemetoda jest lepsza:

Jeśli Android zdecyduje się później odtworzyć Fragment, wywoła konstruktor fragmentu bez argumentu. Przeciążenie konstruktora nie jest rozwiązaniem.

nadal jest całkiem możliwe użycie konstruktora . Aby zrozumieć, dlaczego tak jest, najpierw musimy dowiedzieć się, dlaczego powyższe obejście jest używane przez system Android.

Przed użyciem fragmentu potrzebna jest instancja. Wywołania Androida YourFragment()(konstruktor bez argumentów ) w celu skonstruowania instancji fragmentu. Tutaj każdy przeciążony konstruktor, który napiszesz, zostanie zignorowany, ponieważ Android nie może wiedzieć, którego użyć.

W czasie trwania działania fragment jest tworzony jak wyżej i wielokrotnie niszczony przez Androida. Oznacza to, że jeśli umieścisz dane w samym obiekcie fragmentu, zostaną one utracone po zniszczeniu fragmentu.

Aby obejść ten problem, Android prosi o przechowywanie danych za pomocą Bundle(połączenia setArguments()), do którego można uzyskać dostęp YourFragment. Argumenty bundlesą chronione przez system Android, a zatem gwarantuje się, że będą trwałe .

Jednym ze sposobów ustawienia tego pakietu jest użycie newInstancemetody statycznej :

public static YourFragment newInstance (int data) {
    YourFragment yf = new YourFragment()
    /* See this code gets executed immediately on your object construction */
    Bundle args = new Bundle();
    args.putInt("data", data);
    yf.setArguments(args);
    return yf;
}

Jednak konstruktor:

public YourFragment(int data) {
    Bundle args = new Bundle();
    args.putInt("data", data);
    setArguments(args);
}

może zrobić dokładnie to samo co newInstancemetoda.

Oczywiście to się nie powiedzie i jest to jeden z powodów, dla których Android chce, abyś użył tej newInstancemetody:

public YourFragment(int data) {
    this.data = data; // Don't do this
}

Jako dalsze wyjaśnienie, oto klasa fragmentów Androida:

/**
 * Supply the construction arguments for this fragment.  This can only
 * be called before the fragment has been attached to its activity; that
 * is, you should call it immediately after constructing the fragment.  The
 * arguments supplied here will be retained across fragment destroy and
 * creation.
 */
public void setArguments(Bundle args) {
    if (mIndex >= 0) {
        throw new IllegalStateException("Fragment already active");
    }
    mArguments = args;
}

Pamiętaj, że Android prosi o ustawienie argumentów tylko na etapie budowy i gwarantuje, że zostaną one zachowane.

EDYCJA : Jak wskazano w komentarzach @JHH, jeśli udostępniasz niestandardowy konstruktor, który wymaga pewnych argumentów, wówczas Java nie dostarczy twojemu fragmentowi domyślnego konstruktora bez arg . Wymagałoby to więc zdefiniowania konstruktora no arg , czyli kodu, którego można by uniknąć za pomocą newInstancemetody fabrycznej.

EDYCJA : Android nie pozwala już na używanie przeciążonego konstruktora dla fragmentów. Musisz użyć tej newInstancemetody.


Kiedy uzasadnić użycie Androida: configChanges = "orientacja | keyboardHidden | screenSize"?
Luke Allison

1
Android Studio wyświetla teraz błąd we wszystkich niestandardowych konstruktorach we fragmentach, więc to już nie działa.
Sheharyar

6
Święty człowieku, zastanawiam się, ilu programistów droidów kiedykolwiek napisało kod poza droidem. To szalone, że nie możemy zastosować podejścia, które opisujesz. Z żadnego komentarza NIE ma przekonujących argumentów, dlaczego MAMY używać statycznej metody fabrycznej. Jeszcze bardziej niepokojące jest to, że zgłaszali błąd podczas kompilacji. Jest to zdecydowanie najlepsza podana odpowiedź i pokazuje, że sfm nie przynosi żadnych korzyści.
MPavlak,

3
Jest jeden subtelny powód. Możesz dowolnie tworzyć własny konstruktor z argumentami, ale nadal musi istnieć konstruktor bez argumentu . Ponieważ zajęcia zawsze mają niejawny nie-Arg konstruktora chyba konstruktor z args jest wyraźnie zdefiniowana , oznacza to, że będzie musiał określić zarówno swoje Arg-konstruktor i jest nie-Arg konstruktora jawnie, czy system nie będzie w stanie wywołać dowolny konstruktor bez argumentu. Uważam, że właśnie dlatego zaleceniem jest użycie statycznej metody fabrycznej - po prostu zmniejsza to ryzyko zapomnienia o zdefiniowaniu konstruktora bez argonu.
JHH

@JHH, który zawiedzie w czasie kompilacji, więc nie jest to tak duże ryzyko. Problem polega jednak na tym, że Android zaprzecza przeciążeniu konstruktora, kluczowemu paradygmatowi programowania.
ps95

20

Nie zgadzam się z odpowiedzią yydi mówiącą:

Jeśli Android zdecyduje się później odtworzyć Fragment, wywoła konstruktor fragmentu bez argumentu. Przeciążenie konstruktora nie jest rozwiązaniem.

Myślę, że to rozwiązanie i dobre, to jest właśnie powód, dla którego został opracowany przez podstawowy język Java.

Prawdą jest, że system Android może zniszczyć i odtworzyć Twoje Fragment. Możesz to zrobić:

public MyFragment() {
//  An empty constructor for Android System to use, otherwise exception may occur.
}

public MyFragment(int someInt) {
    Bundle args = new Bundle();
    args.putInt("someInt", someInt);
    setArguments(args);
}

Pozwoli ci to kontynuować someIntod getArguments()ostatniego, nawet jeśli Fragmentzostały odtworzone przez system. To jest bardziej eleganckie rozwiązanie niż statickonstruktor.

Moim zdaniem statickonstruktory są bezużyteczne i nie powinny być używane. Ograniczą cię również, jeśli w przyszłości chcesz to rozszerzyć Fragmenti dodać więcej funkcji do konstruktora. Z statickonstruktorem nie możesz tego zrobić.

Aktualizacja:

System Android dodał inspekcję, która oznacza błąd wszystkich konstruktorów innych niż domyślne.
Polecam ją wyłączyć z wyżej wymienionych powodów.


4
Kolejną zaletą posiadania metody statycznej, o której nie wspomniałem powyżej, jest to, że nie można przypadkowo ustawić z niej właściwości.
yydl

4
Dodatkowo, jeśli chodzi o twoje zdanie na temat „rozszerzenia tego fragmentu”, ta metoda byłaby naprawdę zła, gdybyś kiedykolwiek rozszerzył klasę. Wywołanie super spowoduje, że wywołanie setArguments () będzie skuteczne tylko dla dziecka lub rodzica, ale nie dla obu!
yydl

2
@yydle można uniknąć tej sytuacji, wywołując argumenty get w celu zainicjowania pakietu potomnego. Sposób Java zawsze lepszy.
Ilya Gazman

9
To prawda, ale to kolejny powód, aby zachęcić ludzi do korzystania ze wzoru zaproponowanego przez Google. Oczywiście wszyscy zgadzamy się, że Twoje rozwiązanie jest w 100% technicznie wykonalne. W podobny sposób istnieje wiele sposobów na robienie wielu rzeczy. Pytanie jednak brzmi, czy to jest najlepsze. I mocno czuję, że użycie konstruktora nie odzwierciedla prawdziwej natury tego, jak to powinno działać.
yydl

3
Zgadzam się z @yydl, że tworzenie statyczne jest lepsze. Inną korzyścią jest wstrzykiwanie zależności przyszłych nowych zależności - konstruktor nie jest do tego przystosowany i prawdopodobnie spowoduje więcej zmian w kodzie (lub zostanie dodanych więcej konstruktorów).
Boon

19

Niektóre kody kotlin :

companion object {
    fun newInstance(first: String, second: String) : SampleFragment {
        return SampleFragment().apply {
            arguments = Bundle().apply {
                putString("firstString", first)
                putString("secondString", second)
            }
        }
    }
}

I możesz uzyskać z tym argumenty:

val first: String by lazy { arguments?.getString("firstString") ?: "default"}
val second: String by lazy { arguments?.getString("secondString") ?: "default"}

3

Najlepszą praktyką w przypadku instancji fragmentów z argumentami w Androidzie jest posiadanie statycznej metody fabrycznej we fragmencie.

public static MyFragment newInstance(String name, int age) {
    Bundle bundle = new Bundle();
    bundle.putString("name", name);
    bundle.putInt("age", age);

    MyFragment fragment = new MyFragment();
    fragment.setArguments(bundle);

    return fragment;
}

Należy unikać ustawiania pól za pomocą instancji fragmentu. Ponieważ ilekroć system Android odtworzy Twój fragment, jeśli poczuje, że system potrzebuje więcej pamięci, wówczas odtworzy Twój fragment przy użyciu konstruktora bez argumentów.

Więcej informacji o najlepszych praktykach tworzenia instancji fragmentów z argumentami znajduje się tutaj.


2

Ponieważ mam pytania dotyczące najlepszych praktyk, dodam, że bardzo często dobrym pomysłem jest zastosowanie podejścia hybrydowego do tworzenia fragmentu podczas pracy z niektórymi usługami sieciowymi REST

Nie możemy przekazać złożonych obiektów, na przykład niektórych modeli użytkownika, na wypadek wyświetlenia fragmentu użytkownika

Ale co możemy zrobić, to zarejestrować onCreatetego użytkownika! = Null, a jeśli nie - to zabierz go z warstwy danych, w przeciwnym razie - użyj istniejącego.

W ten sposób zyskujemy zarówno zdolność do odtwarzania przez userId w przypadku odtwarzania fragmentów przez system Android, jak i snappiness do akcji użytkownika, a także możliwość tworzenia fragmentów przez trzymanie się obiektu lub samego jego identyfikatora

Coś lubi to:

public class UserFragment extends Fragment {
    public final static String USER_ID="user_id";
    private User user;
    private long userId;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        userId = getArguments().getLong(USER_ID);
        if(user==null){
            //
            // Recreating here user from user id(i.e requesting from your data model,
            // which could be services, direct request to rest, or data layer sitting
            // on application model
            //
             user = bringUser();
        }
    }

    public static UserFragment newInstance(User user, long user_id){
        UserFragment userFragment = new UserFragment();
        Bundle args = new Bundle();
        args.putLong(USER_ID,user_id);
        if(user!=null){
            userFragment.user=user;
        }
        userFragment.setArguments(args);
        return userFragment;

    }

    public static UserFragment newInstance(long user_id){
        return newInstance(null,user_id);
    }

    public static UserFragment newInstance(User user){
        return newInstance(user,user.id);
    }
}

3
Powiedziałeś: „Nie możemy przekazać złożonych obiektów, na przykład jakiegoś modelu użytkownika” - To nieprawda, możemy. W ten sposób: User user = /*...*/ umieść użytkownika w pakiecie: Bundle bundle = new Bundle(); bundle.putParcelable("some_user", user); i uzyskaj użytkownika z argumentów: User user = getArguments().getParcelable("some_user"); Obiekt musi być zaimplementowany Interfejs działki. link
Adam Varhegyi,

3
Cóż, tak, ale kiedy klasa jest złożona i zawiera odsyłacze do innych obiektów ... Ja osobiście wolę upraszczać, albo mam obiekt, albo go nie mam, a potem muszę go zdobyć
Tigra

1

użyj tego kodu w 100% napraw swój problem

wprowadź ten kod w firstFragment

public static yourNameParentFragment newInstance() {

    Bundle args = new Bundle();
    args.putBoolean("yourKey",yourValue);
    YourFragment fragment = new YourFragment();
    fragment.setArguments(args);
    return fragment;
}

ta próbka wysyła dane logiczne

oraz w SecendFragment

yourNameParentFragment name =yourNameParentFragment.newInstance();
   Bundle bundle;
   bundle=sellDiamondFragments2.getArguments();
  boolean a= bundle.getBoolean("yourKey");

wartość musi w pierwszym fragmencie jest statyczna

szczęśliwy kod


0

Najlepszym sposobem na utworzenie instancji fragmentu jest użycie domyślnej metody Fragment.instantiate lub utworzenie metody fabrycznej w celu utworzenia instancji fragmentu
Uwaga: zawsze twórz jeden pusty konstruktor w innym fragmencie, a przywrócenie pamięci fragmentu spowoduje wygenerowanie wyjątku w czasie wykonywania.


0

Ostatnio tu jestem. Ale coś, co właśnie wiedziałem, może ci trochę pomóc.

Jeśli korzystasz z Javy, nie musisz wiele zmieniać. Ale dla deweloperów kotlin, oto poniższy fragment, który moim zdaniem może sprawić, że będziesz piwnicą:

  • Fragment macierzysty:
inline fun <reified T : SampleFragment> newInstance(text: String): T {
    return T::class.java.newInstance().apply {
        arguments = Bundle().also { it.putString("key_text_arg", text) }
    }
}
  • Normalne połączenie
val f: SampleFragment = SampleFragment.newInstance("ABC")
// or val f = SampleFragment.newInstance<SampleFragment>("ABC")
  • Możesz rozszerzyć rodzicielską operację inicjującą w klasie fragmentów potomnych o:
fun newInstance(): ChildSampleFragment {
    val child = UserProfileFragment.newInstance<ChildSampleFragment>("XYZ")
    // Do anything with the current initialized args bundle here
    // with child.arguments = ....
    return child
}

Szczęśliwego kodowania.


-2

setArguments()jest bezużyteczny. To tylko wprowadza bałagan.

public class MyFragment extends Fragment {

    public String mTitle;
    public String mInitialTitle;

    public static MyFragment newInstance(String param1) {
        MyFragment f = new MyFragment();
        f.mInitialTitle = param1;
        f.mTitle = param1;
        return f;
    }

    @Override
    public void onSaveInstanceState(Bundle state) {
        state.putString("mInitialTitle", mInitialTitle);
        state.putString("mTitle", mTitle);
        super.onSaveInstanceState(state);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) {
        if (state != null) {
            mInitialTitle = state.getString("mInitialTitle");
            mTitle = state.getString("mTitle");
        } 
        ...
    }
}

Tyle że właśnie zostałeś zmuszony do zastąpienia jeszcze jednej metody i utworzenia pola, które mogło być odizolowane dla onViewCreatedzakresu. Myślę, że to wygoda, wiele sposobów na zrobienie tego samego. Jest to także łatwy sposób na sprawdzenie, czy użytkownik wykonał aktualizacje (porównaj pakiety getArgumentsi pakiet z onSaveInstanceState)
Overclover 12.12.2016

@Asagen, podoba mi się twój komentarz na temat porównywania wartości początkowej i wartości użytkownika. Edytowałem kod i uważam, że nadal jest jednolity i przejrzysty bez żadnych getArgumentselementów. Co z onViewCreatedzakresem ... Możemy przywrócić tam pakiet stanu. Ale ja po prostu wolę dokonać onCreateViewlekkiej i szybkiej i wykonać całą ciężką inicjalizację wewnątrz, onActivityCreatedponieważ Fragment.getActivity()czasami lubię wracać nulli ze względu na onAttach()zmiany w nowej wersji API 23.
Vadim Star

Wszystko co robił było tu ruch set i get Argumentsdo saveInstanceState. Zasadniczo robisz to samo, co dzieje się „pod maską”
OneCricketeer

1
@ cricket_007 lub wręcz przeciwnie . Używanie saveInstanceStateto „pod maską”. Korzystanie z Argumentsfunkcji duplikowania powoduje, że sprawdzasz dwukrotnie: najpierw Argumentswartości, a potem saveInstanceStatewartości. Ponieważ musisz użyć w saveInstanceStatejakikolwiek sposób. Co z Arguments... nie są konieczne.
Vadim Star

Argumenty są odpowiednikiem dodatków Intent dla fragmentów. Nie są bezużyteczne, zawierają początkowe parametry, które różnią się od obecnego stanu.
BladeCoder

-12

Wierzę, że mam na to rozwiązanie o wiele prostsze.

public class MyFragment extends Fragment{

   private String mTitle;
   private List<MyObject> mObjects;

   public static MyFragment newInstance(String title, List<MyObject> objects)
   MyFragment myFrag = new MyFragment();
   myFrag.mTitle = title;
   myFrag.mObjects = objects;
   return myFrag;
   }

12
mObjects zostaną usunięte, jeśli MyFragment zostanie odtworzony (użytkownik przejdzie do ekranu głównego urządzenia, a później otworzy aplikację, która została przerwana w MyFragment). Możesz zachować mObjects, wysyłając MyFragment pakiet jako argumenty.
ynnadkrap

1
W jaki sposób metoda statyczna uzyskuje dostęp do niestatycznych zmiennych składowych?
OrhanC1

2
@ynnadkrap Masz rację, skorzystaj z pakietu, aby przejść tutaj.
Stefan Bogaard

2
@ OrhanC1 Zgodnie z tym przykładem, metoda statyczna nie ma dostępu do zmiennych składowych. Instancja MyFragment ma dostęp do swoich członków. Tutaj nie ma błędu. Jednak nie polecam tej odpowiedzi nikomu, ponieważ gdy twój fragment zostanie usunięty z pamięci, aby otworzyć trochę miejsca przez system operacyjny Android, po ponownym uruchomieniu aktywności i ten fragment zostanie utworzony z domyślnym pustym konstruktorem bez przypisywania zmiennych ant.
Gunhan

@Gunhan Masz rację! To nie jest. Przepraszamy za zamieszanie :)
OrhanC1,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.