Polimorfizm. Problem z przypisaniem wartości.

0

Hej,

Mam klasę abstrakcyjną Animal, która jest klasą bazową. Mam też drugą klasę Bear, która dziedziczy po Animal. Po utworzeniu obiektu występuje problem z przypisaniem wartości do zmiennej klasy Bear. Mógłbym użyć konstruktora, ale chcę wiedzieć czemu tak się dzieje, że nie mogę tego zrobić tak jak to przedstawiłem poniżej:

package MainPackage;

public abstract class Animal{
    int id;
    String name;
    float weight;
    void introduce(){
        System.out.println(" My name is " + name + " and my weight is " + weight);
    }
}
class Bear extends Animal{
    int furlength;
    @Override
    void introduce(){
        System.out.println(" My name is " + name + " and my weight is " + weight + ". My fur length is " + furlength);
    }
}
public class Main{
    public static void main(String[] argv){
        Animal bear = new Bear();
        bear.name = "Yogi";
        bear.weight = 200;
        bear.furlength = 40;
    }
}

Blad pojawia się w polu furlength przy przypisywaniu wartości 40. Czy to pole jest prywatne?

PS: Jakieś uwagi dotyczące dobrych praktyk? Poprawić dostepy?

0

No bo masz obiekt typu Animal a nie Bear. Nie wiesz w tym miejscu, że pod spodem jest Bear to i nie masz dostępu do zmiennej.

1

W dużym uproszczeniu przypisując Bear do Animal, masz dostęp tylko do pól i metod z klasy Bear co znajdują się w klasie Animal. Poprzez rzutowanie i ewentualnie instanceof możesz uzyskać dostęp do reszty elementow Bear, ale to moze sobie na razie nie mieszaj ;)

0
DamianSn napisał(a):

W dużym uproszczeniu przypisując Bear do Animal, masz dostęp tylko do pól i metod z klasy Bear co znajdują się w klasie Animal. Poprzez rzutowanie i ewentualnie instanceof możesz uzyskać dostęp do reszty elementow Bear, ale to moze sobie na razie nie mieszaj ;)

Właśnie użyłem rzutowania i działa. Dzięki za pomoc ;)

4

Kilka zasad w Javie:

  • typ referencji określa do jakich składowych masz dostęp
  • wybór konkretnego pola z obiektu zależy od typu referencji (bo pola nie są wirtualne)
  • wybór konkretnej implementacji metody nie zależy od typu referencji (bo metody są wirtualne)

Przykład:

class Parent {
  int i;
  int get() { return i; }
  @Override String toString() { return "parent"; }
}
class Child extends Parent {
  int i; // to pole przesłania pole z rodzica, nie nadpisuje go
  @Override int get() { return i; }
  @Override String toString() { return "child"; }
}

Child asChild = new Child();
Parent asParent = asChild;

// poniższe dwa pola są różne!
asChild.i = 5;
asParent.i = 8;

System.out.println(asChild.i); // wyświetli 5
System.out.println(asParent.i); // wyświetli 8


// wywołana zostanie ta sama implementacja metody, bo niestatyczne nieprywatne metody w Javie są wirtualne
System.out.println(asChild.get()); // wyświetli 5
System.out.println(asParent.get()); // wyświetli 5

System.out.println(asChild); // wyświetli "child"
System.out.println(asParent); // wyświetli "child"
1

Aż dziwnie, że jeszcze nikt tego nie napisał. W przykładzie który podałeś używanie rzutowania to niezbyt dobra praktyka. Generalnie ustawiane pól przez InstancjaKlasy.pole = wartość to też do dobrych zasad programowania nie należy. W Twoim przykładzie wystarczyłoby użyć po prostu konstruktora z parametrami. Czyli


Animal bear = new Bear("Yogi", 200, 40);
1
podroznik napisał(a):

Aż dziwnie, że jeszcze nikt tego nie napisał. W przykładzie który podałeś używanie rzutowania to niezbyt dobra praktyka. Generalnie ustawiane pól przez InstancjaKlasy.pole = wartość to też do dobrych zasad programowania nie należy. W Twoim przykładzie wystarczyłoby użyć po prostu konstruktora z parametrami. Czyli


Animal bear = new Bear("Yogi", 200, 40);

Co racja to racja, ale czasem, żeby komuś ułatwić zrozumienie podstaw nie warto mu za bardzo mieszać

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