Могут ли различные значения подкласса отражаться в унаследованных методах? - PullRequest
3 голосов
/ 20 апреля 2020

Я пытаюсь создать программу, которая поможет мне узнать Наследование с Java. Однако в этом процессе я обнаружил проблему с тем, что, как мне показалось, я выучил.

Программа проста. У меня есть суперкласс под названием Gun и подкласс под названием M1911 . Идея этой программы состоит в том, чтобы просто показать мне, что вам не нужно повторять методы, подобные тому, который я сделал тоже, который называется shoot(). Однако здесь есть проблема. Я хотел, чтобы shoot() распечатал сообщение на консоль со словами

"GunModel: Pew, pew!"

. GunModel и shoot() определены в Gun и подклассе M1911, чтобы иметь значение, отличное от начального значения, унаследованного от Gun . Это будет означать, что если M1911 имеет GunModel == "M1911", метод shoot() будет отражать это, печатая

"M1911: Pew, pew!"

, что все (очевидно?) Не работает, потому что мне кажется, что значение внутри подкласса не влияет на унаследованные методы. Итак, почему это так, если правда. Кроме того, какую Цели наследования я упускаю? Кажется, это больше, чем просто избегать повторения.

Редактировать: Вот мой код, который я должен был дать первым.

public class Gun {  
    protected String GunModel;
    public void shoot() {
        System.out.println(GunModel + ": Pew, pew!");
    }
}

public class M1911 extends Gun {
    public String GunModel = "M1911";
}

Ответы [ 3 ]

3 голосов
/ 20 апреля 2020

Вот что я получил за ваш код (из неформатированного комментария):

public class Gun 
{ protected String GunModel; 
  public void shoot() 
  { System.out.println(GunModel + ": Pew, pew!"); 
  } 
} 

public class M1911 extends Gun 
{ 
  public GunModel = "M1911"; 
}

Как было указано пользователем в комментариях, «GunModel» не может быть переопределен, так что у вас есть здесь две разные переменные с одинаковыми именами.

Вот что вы можете сделать:

public class Gun 
{ 
  protected String GunModel = "Gun"; 
  public void shoot() 
  { System.out.println(GunModel + ": Pew, pew!"); 
  } 
} 

public class M1911 extends Gun 
{ 
  public M1911()
  {
    GunModel = "M1911";
  }
}

После этого, если кто-то выполнит gunVariable = new M1911() и gunVariable.shoot(), он напечатает "M1911: Пью, пью! ".

Есть и другие способы сделать это - GunModel может быть закрытым, и к нему могут обращаться методы getter и setter, а не напрямую.

Слово о коде Java: условно, классы начинаются с заглавных букв, а переменные начинаются со строчных букв. Используя это соглашение, которое соблюдается повсеместно, ваша переменная будет записана как «gunModel» вместо «GunModel»; Преимущество этого состоит в том, что легко определить, какие вещи являются переменными, а какие - классами. И кто-то говорит, какие вещи, начинающиеся со строчной буквы, являются методами, видя, что после них есть парены.

2 голосов
/ 20 апреля 2020

Отдельные атрибуты (то есть поля) не могут быть перезаписаны посредством наследования. Есть много языков, где это возможно, например C# и Python. Однако Java поддерживает только перезапись методов. Есть несколько способов справиться с этим:

  1. Создать метод поставщика «getGunModel», который возвращает GunModel без ссылки на поле.
  2. Если идентификация оружия основана исключительно на его name, создайте enumclass public enum Guns с полем final private String gunName и обратитесь к этому полю в методе shoot(). Этот метод должен быть определен в контексте перечисления, т.е. не переопределять shoot() в каждом перечисленном экземпляре перечисления, а вызывать его динамически:
enum Guns {
    SOMEGUN("M1911"),
    THATGUN("AK-47");

    private final String gunName;

    private Guns(String modelName) {
        this.gunName = modelName;
    }

    public void shoot() {
        System.out.println(this.gunName + ": Pew pew!");
    }
}

// Now we can call Guns.SOMEGUN.shoot(), which will return "M1911: Pew pew!" over stdout

et c.

0 голосов
/ 20 апреля 2020

Когда вы наследуете что-то, вы можете наследовать: поведение и состояние. Состояние в принципе не может быть переопределено, в вашем фрагменте кода экземпляр M1911 в памяти будет фактически иметь 2 «слота» - один GunModel из класса Gun и один GunModel из класса M1911.

Обычно вы не делаете этого в реальных программах.

Поведение с другой стороны может быть переопределено. Под поведением я подразумеваю методы:

class Gun {
    public void shoot() {
        System.out.println("Gun : Pew, pew!");
    }
}

class M1911 extends Gun {
    public void shoot() { // overrides
        System.out.println("M1911 : Pew, pew!");
    }
}
...