Dziedziczenie metody od klasy abstrakcyjnej ale z innym argumentem

0

Mam taki kod:

abstract class Abstra {
    public abstract void fun();
}

class Child1 extends Abstra {
    @Override
    public void fun() {
        // ta metoda tutaj nie ma sensu
    }

    public void fun(int x) {
        // ta metoda ma sens
    }
}

class Child2 extends Abstra {
    @Override
    public void fun() {
        // tylko ta metoda ma sens
    }
}

No i chciałbym żeby metoda fun() była dla wszystkich dzieci klasy Abstra, ale w klasie Child1 ta metoda była z argumentem a w klasie Child2 bez, i nie moge zrobic po prostu

    @Override
    public void fun(int x) {
        // dostaje blad
    }

jak to najrozsądniej zrobić?

2

tak się nie da. Jaki problem chcesz rozwiązać?

0

Mam staw w którym są Fish, Worm, Alg każdy z nich musi mieć metode desire_move() która zwraca gdzie obiekt chce sie przemiescic, w przypadku Worm i Alg nie jest potrzebny argument, natomiast Fish potrzebuje dostac liste otaczających go obiektów aby wiedział gdzie chce się skierować

1

Rozwiązania widzę trzy:

Rozwiązania pierwsze - nie dziedziczyć. No bo skoro nie chesz robić czegoś w rodzaju

Abstra abstr = new Fish();
abstr.desire_move(env);

to dziedziczenie jest niepotrzebne

Rozwiązanie drugie - wszystkim przekazywać parametr. Można w zanadrzu mieć jakiś emptyEnv, żeby przekazywac go Wormsom i Algom

Rozwiązanie trzecie - dziedziczyć ale żeby metoda była generyczna, (chociaż już nie paaiętam czy to w javie się skompiluje)

class Abstra<ENV> {
  public abstract void desire_move(ENV env);
}

class Worm extends Abstra<Unit> {
    @Override
    public void desire_move(Unit env) {
    }
}

Gdzie Unit jest jakimś pustą klasą co nic w sobie nie posiada
Tylko potem jest brzydkie wywołanie: worm.desire_move(Unit.instance)

0

@KamilAdam:

Pomyślałem, że skompiluiję coś w Twojej idei z użyciem Void. Wyszło mi coś takiego. Właściwie nie wiem wyszło czy / nie wyszło. Dla sparametryzowania typu przez Void nie udaje mi się wywołać, można dorobić ideologię, że tak miało być.

Przypuszczenie: swoja klasa Nothing z nie wiem czym, prywatnymi konstruktorami itd by może był dobrym tropem (chyba jak myślałeś o Unit to może tak samo myśleliśmy)

Zostawiam potomnym do eksperymentów.

package com.company;

public class Main {
    abstract static class Test <T> {
      public abstract void func(T x);
    }
    static class X extends Test<Integer>{

        @Override
        public void func(Integer x) {
            
        }
    }
    static class Y extends Test<Void> {

        @Override
        public void func(Void x) {
            
        }
    }
    public static void main(String[] args) {
	// write your code here
        new X().func(123);  // autoboxing
        new Y().func(new Void); <-- kupa
        
    }
}
1
AnyKtokolwiek napisał(a):

Z ciekawostek - Da się w java 8-19 (kiedyś przestanie działać)

import sun.misc.Unsafe;

public class Main {
    abstract static class Test<T> {
        public abstract void func(T x);
    }

    static class X extends Test<Integer> {

        @Override
        public void func(Integer x) {

        }
    }

    static class Y extends Test<Void> {

        @Override
        public void func(Void x) {

        }
    }

    public static void main(String[] args) throws Exception {

        var unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
        unsafeField.setAccessible(true);
        var unsafe = (Unsafe) unsafeField.get(null);

        var paravoid = (Void) unsafe.allocateInstance(Void.class);

        new X().func(123);  // autoboxing
        new Y().func(paravoid);
    }
}
2
Suchy702 napisał(a):

Mam taki kod:

abstract class Abstra {
    public abstract void fun();
}

class Child1 extends Abstra {
    @Override
    public void fun() {
        // ta metoda tutaj nie ma sensu
    }

    public void fun(int x) {
        // ta metoda ma sens
    }
}

class Child2 extends Abstra {
    @Override
    public void fun() {
        // tylko ta metoda ma sens
    }
}

No i chciałbym żeby metoda fun() była dla wszystkich dzieci klasy Abstra, ale w klasie Child1 ta metoda była z argumentem a w klasie Child2 bez, i nie moge zrobic po prostu

    @Override
    public void fun(int x) {
        // dostaje blad
    }

jak to najrozsądniej zrobić?

No jasno widać że tutaj dziedziczenie nie pasuje. Po prostu nie dziedzicz.

Te trzy klasy które mogą się ruszać, widać że mają różny interfejs - przez ten dodatkowy argument, więc nie mogą mieć wspólnego rodzica.

Teraz pytanie Big picture - skąd u Ciebie się wzięła ta klasa abstrakcyjna:

  • robisz sobie program o rybach, i pomyślałeś że tutaj akurat pytanie klasa abstrakcyjna - no to nie pykla, tutaj dziedziczenie nie pasuje
  • chcesz się nauczyć jak używać takich klas odpowiednio - no to musisz znaleźć inne zadanie
0

Nie da się dziedziczyć z innym argumentem. Możesz sobie dopisać metodę o takiej samej nazwie, ale z innym zestawem argumentów, ale jeżeli chcesz dziedziczyć, to tę podstawową metodę i tak będziesz musiał zaimplementować w klasach konkretnych.

W tych rozkminach najbardziej brakuje mi zrozumienia po co ta metoda ma być. Może być tak:

public class Pond{
private List<Creature> creatures = new ArrayList<Creature>();

//called every frame
  public void onClockTick(){
    creatures.forEach(c => c.requestMove(this@Pond);
  }
}

Do tego mamy:

public abstract class Creature{
  public void requestMove(Pond pond);
}
public class Pland extends Creature{
  @Override
  public void requestMove(Pond pond){
    //don't need to do anything, I can't move
  }
}
public class Fish extends Creature{
  @Override
  public void requestMove(Pond pond){
    var position = pond.getNearestCreaturePosition(....);
    this.moveInDirection(position, currentSpeed);
  }
}

Czyli każde stworzonko dostaje obiekt, który umożliwi podjęcie decyzji o tym jaki ruch wykonać, jeżeli potrzebuje jakichś danych, to sobie je pobierze, jak nie potrzebuje, to nie pobierze.

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