zoukankan      html  css  js  c++  java
  • Java的内部类与向上转型

    相关文章:
    内部类及其创建方式

    在前一篇的文章中,我们讨论了内部类的几种创建的方法,但是,我们会注意到,这些内部类的无论是类的定义还是用来得到其对象的get方法都是public的,因此在其它类中可以直接得到这样的内部类的对象。而在实际的应用中,不同于外部类的只能设计成publicdefault,很多时候内部类的定义是为privateprotected的,此时,我们怎样去使用这些内部类呢?

    若我们直接像之前的方法一样去使用这样的内部类,如以下代码:

    public class PizzaStore {
        private class SausagePizza{
            int size;
            private SausagePizza(int size) {this.size = size;}
            public void getName() {System.out.println("Got a SausagePizza of size:	" + size);}
            public int getSize() {return size;}
        }
    
        public SausagePizza getSausagePizza(int size) {
            return new SausagePizza(size);
        }
    }
    

    在这里,我们见到了熟悉的披萨商店,而其中的SausagePizza在这里被定义为private类型,因此,若我们在另一个测试类Test中来直接创建这个类的对象,像如下这样:

    public class Test {
        public static void main(String[] args) {
            PizzaStore store = new PizzaStore();
            PizzaStore.SausagePizza pizza = store.getSausagePizza(5);
        }
    }
    

    便会出现错误:

    Error:(6, 19) java: learning_java.InnerClassTest.PizzaStore.SausagePizza 在 learning_java.InnerClassTest.PizzaStore 中是 private 访问控制
    

    因此,我们可以看到,对于私有的内部类,我们是不能直接在其余的类中创建其对象的,因为我们在类Test中甚至无法获取到PizzaStore.SausagePizza,便无法实现声明,更不用说去创建对象了。

    那么,是不是我们无法在除了PizzaStore类之外的类中得到一个披萨的实例呢?

    答案是既然允许这样定义内部类,我们自然可以获取这样的实例。但是,在这里我们需要借助向上转型为接口的方式来实现。为什么要借助向上转型为接口呢?因为仔细观察上面的报错,其实我们之所以无法得到一个SausagePizza的实例,在阻碍我们的仅仅是在我们想要获取其实例的时候,无法对其进行声明PizzaStore.SausagePizza而已,而如果这个类是某个接口的实现的话呢?那么我们直接用接口声明不就可以了么?

    下面我们继续用我们的披萨商店来作为例子,来看一下我们怎样得到这样的内部类的实例。

    首先,我们先定义一个披萨的接口Pizza

    public interface Pizza {
        public void getName();
    }
    

    然后,我们定义一个起司披萨的内部类来实现这个接口

    public class PizzaStore {
        private class CheesePizza implements Pizza {
            private int size;
            private CheesePizza(int size) {this.size = size;}
            public void getName() {System.out.println("Got a CheesePizza of size:	" + size);}
            public int getSize() {return size;}
        }
    
        private class SausagePizza{
            private int size;
            private SausagePizza(int size) {this.size = size;}
            public void getName() {System.out.println("Got a SausagePizza of size:	" + size);}
            public int getSize() {return size;}
        }
    
        public Pizza getCheesePizza(int size) {
            return new CheesePizza(size);
        }
    
        public SausagePizza getSausagePizza(int size) {
            return new SausagePizza(size);
        }
    }
    

    我们可以看到,在这里新定义的起司披萨CheesePizza与之前的香肠披萨SausagePizza在定义上没有任何不同,只是实现了Pizza接口而已,而用于创建这个内部类的实例的方法getCheesePizza的类型也用其实现的接口Pizza来进行声明,这样,我们在测试程序中便可以用接口的类型Pizza来声明我们所想要创建的实例,如下:

    public class Test {
        public static void main(String[] args) {
            PizzaStore store = new PizzaStore();
            Pizza pizza = store.getCheesePizza(5);
            pizza.getName();
        }
    }
    

    程序运行结果:

    Got a CheesePizza of size:	5
    

    大功告成!

    但是,有一点我们需要注意,我们在接口中仅定义了一个方法getName(),而在Test中声明的实例变量pizza的类型为接口Pizza,因此对于这个实例,我们只能调用getName()方法,而不能调用我们在内部类CheesePizza时定义的另一个方法getSize(),否则会报错,例子如下:

    public class Test {
        public static void main(String[] args) {
            PizzaStore store = new PizzaStore();
            Pizza pizza = store.getCheesePizza(5);
            pizza.getName();
            // getSize()方法并没有在接口Pizza中声明,因此在这里并不能调用该方法
            pizza.getSize();
        }
    }
    

    编译报错:

    Error:(8, 14) java: 找不到符号
      符号:   方法 getSize()
      位置: 类型为learning_java.InnerClassTest.Pizza的变量 pizza
    

    由这一点,我们可以看到,private类型的内部类,在其它类中是完全不可见的,且其所实现接口之外的所有方法是不可用的。在这里,我们所得到的只是指向基类或接口的引用,所以能够很方便地隐藏实现细节。

    由于不能访问任何新增加的、原本不属于公共接口的方法,所以扩展接口是没有太多必要的。

  • 相关阅读:
    光遇————墓土(补充)蜡烛收集
    光遇————雨林
    每日光遇日记
    光遇————墓土
    光遇————云野超级不详细的蜡烛收集
    光遇————晨岛超级详细的蜡烛收集
    高精度
    HDU 1002: A + B Problem II (大数加法)
    HDU 1018:Big Number (位数递推公式)
    D2. Remove the Substring (hard version) (KMP-next数组 ) ( Codeforces Round #579 (Div. 3) )
  • 原文地址:https://www.cnblogs.com/liulaolaiu/p/11744424.html
Copyright © 2011-2022 走看看