【问题标题】:Java: Creating Reference Type from Abstract class and interfaceJava:从抽象类和接口创建引用类型
【发布时间】:2014-12-04 12:44:53
【问题描述】:

我是 Java 新手,我已经阅读了无法实例化抽象类的线程 (here)。所以,我测试了一下。

我做的第一个测试如下所示。看起来我实际上可以实例化一个抽象类,实际上,我实际上有一个新的 type 引用抽象类,并且该类型实际上由扩展它的所有子类共享。这也意味着适用多态性。

import java.util.*;

abstract class AbstractClass{
    public abstract void printname();
}


class Test1 extends AbstractClass{

    private String name;

    public Test1(String name){
        this.name = name;
    }

    public void printname(){
        System.out.println("My name is " + name);
    }
}

class Test2 extends AbstractClass{
        private String saysomething;

    public Test2(String saysomething){
        this.saysomething = saysomething;
    }

    public void printname(){
        System.out.println(saysomething);
    }
}

class TestingApp{
    public static void main(String[] args){
        AbstractClass[] abstractclass_list = {new Test1("JEFFFFFF") , new Test2("Hey , say something")};
        for(AbstractClass item : abstractclass_list){
            item.printname();
        }
    }
}

然后我又做了一个测试,但这一次,我决定创建一个引用接口的类型,而不是抽象类。似乎我也可以实例化一个接口。我实际上可以创建一个引用接口的 type。此类型由实现此接口的所有类共享。并且多态性再次适用。

import java.util.*;

interface  AbstractInterface{
    public void printname();
}


class Test4 implements AbstractInterface{

    private String name;

    public Test4(String name){
        this.name = name;
    }

    public void printname(){
        System.out.println("My name is " + name);
    }
}

class Test3 implements AbstractInterface{
    private String saysomething;

    public Test3(String saysomething){
        this.saysomething = saysomething;
    }

    public void printname(){
        System.out.println(saysomething);
    }
}

class TestingAbstractInterfaceApp{
    public static void main(String[] args){
        AbstractInterface[] abstract_list = {new Test4("Helen") , new Test3("Hey , say my name")};
        for(AbstractInterface item : abstract_list){
            item.printname();
        }
    }
}

问题:

我感觉到我在代码中所做的事情有问题。但是我不能完全解释为什么代码在理论上仍然可以工作,不可能实例化一个抽象类和接口。我实际上是在上面显示的示例中实例化一个抽象类和一个接口吗?因为这似乎正是我所做的,因为我有一个新的抽象类和接口类型。请纠正我,如果我的逻辑是错误的或者我使用了错误的词。

更新: 所以我想我的误解是关于type。我一直认为类型只能指普通的Java类,不能指抽象类和接口。 “类型”实际上是如何工作的?它是在创建参考吗?

【问题讨论】:

    标签: java oop interface abstract-class


    【解决方案1】:

    为什么你认为你实际上是在实例化AbstractClassAbstractInterface

    new Test1("JEFFFFFF") , new Test2("Hey , say something"), new Test4("Helen") , new Test3("Hey , say my name") 都是实例化具体类,而不是抽象类。

    如果您将AbstractClass[] abstractclass_list = 称为实例化抽象类的证明,那是错误的。在这里,您声明了一个数组,其元素的类型为 AbstractClass,而 Test1Test2 是(因为它们是 extend AbstractClass)。

    更新

    你可以有类似AbstractClass abs = new Test1("hey"); 的东西,它的作用是创建一个类Test1 的新实例,并从变量abs 引用该实例。 abs 的具体类型是 Test1,但只有在 AbstractClass 中声明的方法在其上可见。如果你想调用Test1的方法,你必须先转换它。

    AbstractClass abs = new Test1("hey");
    abs.printname(); // this is ok, and it calls `printname() implemented in Test1
    abs.someTest1Method(); // this is NOT ok, someTest1Method() is not visible to abs
    ((Test1)abs).someTest1Method(); // this is ok, abs is cast to Test1, but would fail if abs was instantiated as 'abs = new Test2("t2")' (would throw ClassCastException)
    

    【讨论】:

    • @Chinegro 关于您的更新,我已经编辑了我的答案。
    • 这是使用多态的问题吧?无论超类是否抽象,只有超类的方法对子类可见。正确吗?
    • 我不会称之为问题,但这就是它的表现方式。
    • 我应该说“问题”。非常感谢你。我开始意识到 OOP 可以变得非常抽象,有时您可以通过创建抽象类或接口来完成相同的任务,但决定使用哪个是困难的部分。
    • 这是 Java 的重要组成部分,以JPA 为例。它是一个复杂而强大的框架,但它本身只是一个接口的集合。它需要实现这些接口才能真正做任何事情。
    【解决方案2】:

    您没有实例化您的抽象类或接口。您正在实例化扩展抽象类(Test1Test2)或实现接口(@98​​7654323@ 和 Test4)的具体类。

    允许将具体类的实例分配给类型为接口或抽象类的变量。事实上,它甚至受到鼓励。

    【讨论】:

      【解决方案3】:

      您既没有实例化抽象类,也没有实例化接口。您只是在使用从子类到超类的固有向上转换能力。

      忽略数组,只使用第一个对象,这相当于隐式向上转换:

      AbstractClass myObject = new Test1("JEFFFFFF");
      

      AbstractInterface myObject = new Test1("JEFFFFFF");
      

      所以,在代码中:

        AbstractClass[] abstractclass_list = {
           new Test1("JEFFFFFF") , 
           new Test2("Hey , say something")};
      

      您正在实例化具体类 Test1Test2 的对象 - 数组包含对底层(和通用)抽象基类的引用。

      同样,在第二个示例中,您将获得一个接口引用数组。

      【讨论】:

        【解决方案4】:

        总之我想说的是,
        Parent(here, Abstract/Iterface)可以参考,是child(here, concrete class)

        所以在这里,引用变量可以引用它的子类的实例。

        只要在你的大脑中记下这个概念,它就会解决你所有关于动态调度程序、继承相关的问题......!!!

        【讨论】:

          【解决方案5】:

          你不是 instantiating 一个 abstract 类和一个 interface

          你是 instantiating 某个特定的 implementations abstract 类和 interface

          如果您声明AbstractClassAbstractInterface 的列表,您可以只调用在您的超类或接口上声明的方法,但不能调用在您的特定实现(Test1、Test2、Test3 和 Test4)上声明的方法。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-07-14
            • 1970-01-01
            • 2013-05-14
            • 1970-01-01
            • 1970-01-01
            • 2011-05-18
            • 2011-12-05
            相关资源
            最近更新 更多