Typy generyczne

0

Cześć

Staram się nadrobić wiedzę z typów generycznych i mam kilka pytań:

  1. Mam taki kod:
{
        static void Main()
        {
            var inty = Metoda1("okon");
            Console.WriteLine(inty);
        }

        public static T Metoda1<T>(T zmienna1)
        {
            return zmienna1;
        }
}

Teraz chciałem operwoać na konkretnym obiekcie, czyli zrobić coś takiego:

{
        public Generyki g1;
        static void Main()
        {
            g1 = Metoda2("okon");
        }

        public T Metoda2<T>(T zmienna2)
        {
            return zmienna2;
        }

Kompilator mi na coś takiego nie pozwala, co źle robię?

  1. Drugie pytanie jest związane z pierwszym, chodzi mi o kod ze strony LINK
    Jest tam taka konstrukcja:
public Rigidbody rb;
rb = GetComponent<Rigidbody>();
rb.velocity = new Vector3(0, 10, 0);

Pierwsza linijka to referejncja do obiektu klasy Rigidbody. Druga to użycie metody GetComponent z zadeklarowanym typem Rigidbody bez podania żadnych parametrów?
I nie rozumiem czemu trzeba było zrobić w ten sposób, żeby w trzeciej linijce zadeklarować użycie metody Velocity z konkretnym konstruktorem.
Da się to przedstawić na jakimś prostym przykładzie co się pod tym kryje?

1

Było by prościej jakbyś napisał błąd kompilatora.
Kod:

{
    public String g1;
    static void Main()
    {
        g1 = Metoda2("okon");
    }

    public T Metoda2<T>(T zmienna2)
    {
        return zmienna2;
    }

powinien działać na moją Javową głowę.

UPDATE z poprawkami @Delor:

{
    public static String g1;
    public static void Main()
    {
        g1 = Metoda2("okon");
    }

    public static T Metoda2<T>(T zmienna2)
    {
        return zmienna2;
    }
0
Kamil Żabiński napisał(a):

Taki komunikat dostaję

an object reference is required for the non-static field method or property 'Generyki.g1'

Zastanawiałem się jak użyć typu generycznego z konkretnym obiektym (tak jak to robi dla mnie wrażenie w drugim podpunkcie)

2

Taki komunikat dostajesz, bo przekazujesz niestatyczne pole do statycznej metody.

0
Sarrus napisał(a):

Taki komunikat dostajesz, bo przekazujesz niestatyczne pole do statycznej metody.

{
    public Generyki g1;
    static void Main()
    {
        g1 = Metoda2("okon");
    }

    public T Metoda2<T>(T zmienna2)
    {
        return zmienna2;
    }
}

Metoda też jest niestatyczna.
Chyba, że miałeś na myśli metodą Main. Ale przenosząc wywołanie do innej metody dostaję komunikat:

cannot implicitly convert type 'string' to 'Nauka.Generyki'

2

A to przepraszam. Wywołujesz niestatyczną metodę w statycznej metodzie.

1

Jak chcesz wywołać niestatyczną metodę to najpierw musisz utworzyć obiekt .
Do niestatycznych składowych dostajesz się przez obiekt ( np. nazwa_obiektu.Metoda() albo this.Metoda() )
a do statycznych przez klasę ( nazwa_klasy.Metoda() albo z wnętrza klasy Metoda() )
This i nazwa klasy są automatycznie dodawane przez kompilator C# jeśli wywołujesz składową z wnętrza klasy.

To są podstawy

0

Rzeczywiście macie rację, przy pierwszym podpunkcie popełniłem błąd, bo wrzucałem niestatyczną metodą do statycznej i zignorowałem komunikat kompilatora. Drugiego podpunktu dalej nie rozumiem.
Głównie nie wiem co robi taki zapis:

rb = GetComponent<Rigidbody>();

Do referencji klasy przypisuję wynik metody z podanym typem generycznym Rigidbody? I po co podaję ten typ generyczny kiedy nie używam żadnego parametru? I jak to się ma w dalszej części do tego kawałka kodu:

rb.velocity = new Vector3(0, 10, 0);

Jak wpływa na ten obiekt wywołanie w taki sposób tej etody Rigidbody?

2

Wiesz co ciężko będzie Tobie to wytłumaczyć w kilku zdaniach, bo brakuje Tobie elementarnej wiedzy na ten temat. Forum nie jest od tego, żeby robić wykłady. Postaram się nakreślić Tobie pokrótce:

Weźmy najczęściej wykorzystywaną klasę generyczną jaką jest List<T>. W takiej "surowej" postaci ten typ jest niedomknięty (niepełny). Żeby go użyć potrzebujesz podać parametr np:

var list = new List<int>();

Kompilator utworzy dla Ciebie klasę List<int>. Klasa ta ma metodę void Add(T item), więc w tym przypadku będzie to void Add (int item). Jeżeli napiszesz:

var item = list[0];

item będzie typu int
jeżeli napiszesz

var list = new List<string>();
/* .... */
var item = list[0];

to będziesz miał nową klasę, a item będzie typu string.

0
Sarrus napisał(a):

Wiesz co ciężko będzie Tobie to wytłumaczyć w kilku zdaniach, bo brakuje Tobie elementarnej wiedzy na ten temat. Forum nie jest od tego, żeby robić wykłady. Postaram się nakreślić Tobie pokrótce:

Weźmy najczęściej wykorzystywaną klasę generyczną jaką jest List<T>. W takiej "surowej" postaci ten typ jest niedomknięty (niepełny). Żeby go użyć potrzebujesz podać parametr np:

var list = new List<int>();

Kompilator utworzy dla Ciebie klasę List<int>. Klasa ta ma metodę void Add(T item), więc w tym przypadku będzie to void Add (int item). Jeżeli napiszesz:

var item = list[0];

item będzie typu int
jeżeli napiszesz

var list = new List<string>();
/* .... */
var item = list[0];

to będziesz miał nową klasę, a item będzie typu string.

O typach generyczych czytałem w jednej książce ale ciężko jest mi to przełożyć na ten konkretny przypadek, bo ten kod nie wygląda w ten sposób:

rb = new GetComponent<Rigidbody>();

Czemu tutaj nie muszę jawnie tworzyć nowego obiektu?

Rozumiem, że temat generyków nie jest dobry do omawiania na forum ale jak wspomniałem, czytałem o generykach ale ten przykład jest inny niż ten z którym się spotkałem. Twój przykład do mnie przemawia bo jest podobny do tego, który przerabiałem w książce.

4

Nie tworzysz nowego obiektu, dostajesz obiekt, który już jest. W Unity metoda GetComponent<T> zwraca ci komponent typu T powiązany z aktualnym obiektem (typu GameObject o ile dobrze pamiętam). Musisz do tej metody przekazać do jakiego typu obiektu chcesz dostać referencję. Każdy komponent przypisywany do GameObject jest też przecież obiektem.

Równie dobrze ta metoda mogła by być wywoływana jako GetComponent(typeof(Rigidbody)), zapis GetComponent<T> jest po prostu łatwiejszy i czytelniejszy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1