JavaRush /Java 博客 /Random-ZH /嵌套类的继承

嵌套类的继承

已在 Random-ZH 群组中发布
你好!今天我们来看看嵌套类中一个重要机制的运作方式——继承。我不知道你是否想过当你需要从其他类继承一个嵌套类时你会做什么。如果没有,请相信我:这种情况可能会令人困惑,因为这里有很多细微差别:
  1. 我们是从某个类继承嵌套类,还是从嵌套类继承另一个类?
  2. 继承者/继承者是常规的公共类,还是也是嵌套类?
  3. 最后,我们在所有这些情况下使用的嵌套类到底是什么类型?
如果你回答了所有这些问题,就会有太多可能的答案,让你头晕目眩:) 如你所知,为了解决一个复杂的问题,你需要将其分成更简单的部分。这就是我们要做的。我们从两个角度依次来看每组嵌套类:谁可以继承该类型的嵌套类,以及它可以继承谁。让我们从静态嵌套类开始。

静态嵌套类

内部类的继承示例 - 2他们的继承规则是最简单的。在这里您几乎可以做任何您想做的事情。静态嵌套类可以继承自:
  • 普通班
  • 在外部类或其祖先中声明的静态嵌套类
让我们记住讲座中有关静态嵌套类的示例。
public class Boeing737 {

   private int manufactureYear;
   private static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Drawing {

       public static int getMaxPassengersCount() {

           return maxPassengersCount;
       }
   }
}
让我们尝试更改代码并创建一个静态嵌套类Drawing及其后代 - Boeing737Drawing
public class Boeing737 {

   private int manufactureYear;
   private static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Drawing {

   }

   public static class Boeing737Drawing extends Drawing {

       public static int getMaxPassengersCount() {

           return maxPassengersCount;
       }
   }
}
正如你所看到的,没问题。我们可以完全删除该类Drawing,并将其设为常规公共类,而不是静态嵌套类 - 不会有任何改变。
public class Drawing {

}

public class Boeing737 {

   private int manufactureYear;
   private static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Boeing737Drawing extends Drawing {

       public static int getMaxPassengersCount() {

           return maxPassengersCount;
       }
   }
}
就这么解决了 哪些类可以从静态嵌套类继承?几乎任何!嵌套/常规、静态/非静态 - 没关系。Boeing737Drawing这里我们从静态嵌套类继承内部类Drawing
public class Boeing737 {

   private int manufactureYear;
   private static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Drawing {

   }

   public class Boeing737Drawing extends Drawing {

       public int getMaxPassengersCount() {

           return maxPassengersCount;
       }
   }
}
Boeing737Drawing您可以像这样 创建一个实例:
public class Main {

   public static void main(String[] args) {

      Boeing737 boeing737 = new Boeing737(1990);
      Boeing737.Boeing737Drawing drawing = boeing737.new Boeing737Drawing();
      System.out.println(drawing.getMaxPassengersCount());

   }

}
虽然我们的类Boeing737Drawing继承自静态类,但它本身并不是静态的!因此它总是需要外部类的实例。我们可以把课程Boeing737Drawing从课堂中拿出来Boeing737,让它变成公开课。什么都不会改变——它也可以从静态嵌套继承Drawing
public class Boeing737 {

   private int manufactureYear;
   public static int maxPassengersCount = 300;

   public Boeing737(int manufactureYear) {
       this.manufactureYear = manufactureYear;
   }

   public int getManufactureYear() {
       return manufactureYear;
   }

   public static class Drawing {

   }
}

public class Boeing737Drawing extends Boeing737.Drawing {

   public int getMaxPassengersCount() {

       return Boeing737.maxPassengersCount;

}
唯一重要的一点:在这种情况下,我们需要将静态变量maxPassengersCount公开。如果它保持私有,普通的公共类将无法访问它。我们整理出了静态类!:) 现在让我们继续讨论内部类。正如您所记得的,它们有 3 种类型:简单内部类、本地类和匿名内部类。 内部类的继承示例 - 3再次,让我们从简单到复杂:)

匿名内部类

匿名内部类不能从另一个类继承。任何其他类都不能从匿名类继承。简单得不能再简单了!:)

本地课程

本地类(以防您忘记)在另一个类的代码块内声明。最常见的是 - 在这个外部类的某些方法内。从逻辑上讲,只有同一方法(或块)中的其他本地类可以从本地类继承。这是一个例子:
public class PhoneNumberValidator {

   public void validatePhoneNumber(final String number) {

       class PhoneNumber {

           private String phoneNumber;

           public PhoneNumber() {
               this.phoneNumber = number;
           }

           public String getPhoneNumber() {
               return phoneNumber;
           }

           public void setPhoneNumber(String phoneNumber) {
               this.phoneNumber = phoneNumber;
           }
       }

       class CellPhoneNumber extends PhoneNumber {

       }

       class LandlinePhoneNumber extends PhoneNumber {


       }

       //...code валидации номера
   }
}
这是我们有关本地课程的讲座中的代码。在数字验证器类中,我们有一个本地类PhoneNumber- 电话号码。如果出于我们的目的,我们需要将两个单独的实体从中分离出来,例如,移动电话号码和固定电话号码,我们只能在相同的方法中执行此操作。原因很简单:本地类的范围位于声明它的方法(块)内。因此,我们将无法以某种方式在外部使用它(包括继承)。然而,本地类本身具有更广泛的继承可能性!本地类可以继承自:
  1. 正常上课。
  2. 在与本地类或其祖先相同的类中声明的内部类。
  3. 来自在同一方法(块)中声明的另一个本地类。
第一点和第三点看起来很明显,但第二点有点令人困惑:/让我们看两个例子。示例 1 - “从与本地类在同一类中声明的内部类继承本地类”:
public class PhoneNumberValidator {

   class PhoneNumber {

       private String phoneNumber;

       public PhoneNumber(String phoneNumber) {
           this.phoneNumber = phoneNumber;
       }

       public String getPhoneNumber() {
           return phoneNumber;
       }

       public void setPhoneNumber(String phoneNumber) {
           this.phoneNumber = phoneNumber;
       }
   }

   public void validatePhoneNumber(final String number) {

       class CellPhoneNumber extends PhoneNumber {

           public CellPhoneNumber(String phoneNumber) {
               super(number);
           }
       }

       class LandlinePhoneNumber extends PhoneNumber {

           public LandlinePhoneNumber(String phoneNumber) {
               super(number);
           }
       }

       //...code валидации номера
   }
}
在这里,我们将类PhoneNumber从方法中取出validatePhoneNumber()并使其成为内部的而不是本地的。这并不妨碍我们继承它的 2 个本地类。示例 2 – “……或者在这个类的祖先中。” 这就是事情变得更有趣的地方。我们可以把它带到PhoneNumber更高的继承链上。让我们声明一个抽象类AbstractPhoneNumberValidator,它将成为我们的祖先PhoneNumberValidator
public abstract class AbstractPhoneNumberValidator {

   class PhoneNumber {

       private String phoneNumber;

       public PhoneNumber(String phoneNumber) {
           this.phoneNumber = phoneNumber;
       }

       public String getPhoneNumber() {
           return phoneNumber;
       }

       public void setPhoneNumber(String phoneNumber) {
           this.phoneNumber = phoneNumber;
       }
   }

}
正如你所看到的,我们不仅声明了它,而且还将内部类移入其中PhoneNumber。然而,在其后代类——PhoneNumberValidator方法中的本地类可以继承PhoneNumber
public class PhoneNumberValidator extends AbstractPhoneNumberValidator {

   public void validatePhoneNumber(final String number) {

       class CellPhoneNumber extends PhoneNumber {

           public CellPhoneNumber(String phoneNumber) {
               super(number);
           }
       }

       class LandlinePhoneNumber extends PhoneNumber {

           public LandlinePhoneNumber(String phoneNumber) {
               super(number);
           }
       }

       //...code валидации номера
   }
}
由于通过继承进行连接,后代类中的本地类“看到”祖先类中的内部类。最后,让我们继续最后一组:)

内部类

内部类可以被同一外部类(或其后代)中声明的另一个内部类继承。让我们使用内部类讲座中的自行车示例来看看这一点。
public class Bicycle {

   private String model;
   private int mawWeight;

   public Bicycle(String model, int mawWeight) {
       this.model = model;
       this.mawWeight = mawWeight;
   }

   public void start() {
       System.out.println("Go!");
   }

   class Seat {

       public void up() {

           System.out.println("Сидение поднято выше!");
       }

       public void down() {

           System.out.println("Сидение опущено ниже!");
       }
   }

   class SportSeat extends Seat {

       //...methods
   }
}
这里我们在类内部Bicycle声明了一个内部类Seat——seat。赛车座椅的特殊子类型继承自它 - SportSeat。但是,我们可以创建一种单独类型的“赛车”并将其放入单独的类中:
public class SportBicycle extends Bicycle {

   public SportBicycle(String model, int mawWeight) {
       super(model, mawWeight);
   }


   class SportSeat extends Seat {

       public void up() {

           System.out.println("Сидение поднято выше!");
       }

       public void down() {

           System.out.println("Сидение опущено ниже!");
       }
   }
}
这也是有可能的。子级的内部类 ( SportBicycle.SportSeat) “看到”祖先的内部类并可以继承它们。从内部类继承有一个非常重要的特性!在前面的两个例子中,我们SportSeat有内部的。但是,如果我们决定将其设为SportSeat常规公共类,并且它也继承自内部类,该怎么办Seat
//ошибка! No inclosing instance of  type 'Bicycle' is in scope
class SportSeat extends Bicycle.Seat {

   public SportSeat() {

   }

   public void up() {

       System.out.println("Сидение поднято выше!");
   }

   public void down() {

       System.out.println("Сидение опущено ниже!");
   }
}
我们遇到错误!你能猜出它与什么有关吗?:) 这很简单。当我们讨论内部类时Bicycle.Seat,我们提到内部类的构造函数隐式传递了对外部类对象的引用。因此,不创建对象Bicycle就无法创建对象Seat。创作呢SportSeat?它没有与 中相同的内置机制来隐式传递对构造函数中外部类对象的引用Seat。但是,如果没有对象Bicycle,就像有的情况一样Seat,我们无法创建对象SportSeat。因此,我们只剩下一件事要做——显式地将SportSeat对象的引用传递给构造函数。Bicycle其操作方法如下:
class SportSeat extends Bicycle.Seat {

   public SportSeat(Bicycle bicycle) {

       bicycle.super();
   }

   public void up() {

       System.out.println("Сидение поднято выше!");
   }

   public void down() {

       System.out.println("Сидение опущено ниже!");
   }
}
为此,我们使用一个特殊的词super(); 现在,如果我们想创建一个对象SportSeat,没有什么可以阻止我们这样做:
public class Main {

   public static void main(String[] args) {

       Bicycle bicycle = new Bicycle("Peugeot", 120);
       SportSeat peugeotSportSeat = new SportSeat(bicycle);

   }
}
唷,讲座内容相当大:)但是你学到了很多新东西!现在是解决一些问题的时候了!:)
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION