简体   繁体   English

接口是对象的实例,而对象是Java中接口的实例吗?

[英]Interfaces are instances of objects and objects are instances of Interfaces in Java?

I have an interface defined called IntF 我有一个定义为IntF的接口

I also have a Class defined called Cls which implements IntF . 我还定义了一个名为Cls的类, IntF实现IntF

And here is some client code: 这是一些客户端代码:

IntF i=new Cls();
Cls c=new Cls();
System.out.print(i instanceof Cls);
System.out.print(c instanceof IntF);

the output is truetrue 输出为truetrue

Why exactly is this the output? 为什么这是输出? I figured it would've been falsefalse . 我认为那将是falsefalse

I thought that i would be an instance of IntF , but that doesn't make sense because you can't really initialize interfaces right? 我以为i将是IntF的实例,但这没有任何意义,因为您无法真正初始化接口,对吗? Or can you? 可以吗 I'm comfortable with Java, but this stuff is a little fuzzy. 我对Java很满意,但是这个东西有点模糊。

Any help is appreciated. 任何帮助表示赞赏。

Both i and c hold a reference to an instance of the Cls class. ic持有对Cls类实例的引用。 Therefore both are instanceof Cls . 因此,两者都是instanceof Clsinstanceof Cls And since Cls class implements the IntF interface, both are instanceof IntF . 并且由于Cls类实现了IntF接口,因此它们都是instanceof IntF

the keyword instanceof is misleading here. 关键字instanceof在这里具有误导性。 The meaning of a instanceof B is: a instanceof B的含义是:

object referenced to by variable a provides all methods defined in class or interface B because the type of object referenced by a (its class) is a descendant of class or interface B by any means of java inheritance. 变量a引用的对象提供了在接口 B定义的所有方法,因为a (其类)引用的对象的类型是通过任何Java继承的接口 B的后代。


So i would only have access to the methods defined in the IntF interface, whereas c would have access to the methods defined the Cls class? 所以我只能访问IntF接口中定义的方法,而c可以访问Cls类定义的方法? And using instanceof just tells whether or not B has access to all methods defined in whatever class or interface A adheres to? 使用instanceof可以告诉B是否可以访问A遵循的任何类或接口中定义的所有方法? – Angel Garcia –天使加西亚

It is not so much a question of "having access". 它不是“具有访问权限”的问题。 The question answered by 回答的问题
a instenceof B is: Can I store the object in a in a variable of type B (and then access methods only available in B ). a instenceof B是:可以在对象存储a在类型的变量B然后访问方法只适用于B )。

if(i instanceof Cls)
   Cls i2= (Cls)i;   

But
Do not invest too much effort in understanding instanceof . 不要花太多的精力来理解instanceof You should never need it in real life since it is a tool to effectively prevent you from using the most valuable benefit of OOP: polymorhism . 在现实生活中,您永远都不需要它,因为它是一种有效地阻止您使用OOP的最有价值的好处: 多态性的工具

Object.getClass

The other two Answers are correct about instanceof . 关于instanceof ,其他两个答案是正确的。 It might clarify your thinking to know that you can also obtain the actual concrete class of an instance. 知道您还可以获得实例的实际具体类可能会澄清您的想法。

Every class in Java extends from Object class. Java中的每个类都从Object类扩展而来。 And Object includes a getClass method. Object包含一个getClass方法。 That method returns an object of type Class — but do not think about that too much or it makes your head hurt. 该方法返回Class类型的对象-但不要考虑太多,否则会伤到头部。 The real point here is that you can then ask for the textual name of the concrete class behind your particular instance. 这里的重点是,您可以随后在特定实例后面询问具体类的文本名称。

String className = someInstance.getClass().getName() ;

Below is an example of an interface Animal and 3 classes implementing that interface, Cat , Dog , Chihuahua . 下面是一个接口Animal的示例,以及实现该接口的3个类CatDogChihuahua The Chihuahua class extends Dog to yip instead of bark. Chihuahua班级将Dog延伸到yip而不是树皮。 We instantiate all 3 concrete classes but hold each instance as the more general Animal interface. 我们实例化所有3个具体类,但将每个实例都保留为更通用的Animal接口。 Note we can get the most specific subclass of an instance, such as Dog versus Chihuahua . 注意,我们可以获得实例的最具体的子类,例如Dog vs Chihuahua

import java.util.*;
import java.lang.*;
import java.io.*;

/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        Animal animal1 = new Cat() ;
        animal1.speak() ;
        System.out.println( animal1.getClass().getName() ) ;

        Animal animal2 = new Dog() ;
        animal2.speak() ;
        System.out.println( animal2.getClass().getName() ) ;

        Animal animal3 = new Chihuahua() ;
        animal3.speak() ;
        System.out.println( animal3.getClass().getName() ) ;
    }
}

interface Animal {
    public void speak() ;
}

class Dog implements Animal {
    @Override
    public void speak() {
        System.out.println( "Bark." ) ;
    }
}

class Chihuahua extends Dog {
    @Override
    public void speak() {
        System.out.println( "Yip." ) ;
    }
}


class Cat implements Animal {
    @Override
    public void speak() {
        System.out.println( "Meow." ) ;
    }
}

See this code run live at IdeOne.com. 看到此代码在IdeOne.com上实时运行。

Meow. 喵。

Cat

Bark. 吠。

Dog

Yip. 是的

Chihuahua 奇瓦瓦州


I thought that i would be an instance of IntF, but that doesn't make sense because you can't really initialize interfaces right? 我以为我将是IntF的实例,但这没有任何意义,因为您无法真正初始化接口,对吗? Or can you? 可以吗

No, you cannot instantiate an interface in Java. 不可以,您不能在Java中实例化接口。

But the point of polymorphism (“many shapes”) is that you can instantiate an object from a class with say 5 methods, yet hold a reference to the object as if it were of the interface only, with say 3 methods. 但是多态 (“许多形状”)的要点是,您可以使用5种方法实例化一个类的对象,而使用3种方法将对象的引用视为仅是接口的引用。 When you invoke methods on the object through that reference, you can only invoke the 3 methods. 通过该引用在对象上调用方法时,只能调用3个方法。 The compiler will not allow you to call the other 2 of the 5 methods on the class, because from the point of view of the interface, those other two methods do not exist. 编译器不允许您调用该类中5个方法中的另外2个,因为从接口的角度来看,这两个方法不存在。 I think of this (holding a reference to an object as a interface) like looking through a color filter lens, blocking out some wavelengths while allowing other wavelengths to pass through. 我想到了这一点(将对对象的引用作为接口),就像通过滤色镜查看一样,遮挡了某些波长,同时允许其他波长通过。

I'm comfortable with Java, but this stuff is a little fuzzy. 我对Java很满意,但是这个东西有点模糊。

Don't worry, let it be fuzzy. 别担心,让它变得模糊。 Practice brings clarity . 实践带来清晰 Thinking about it abstractly (pun intended) makes the concepts difficult to grasp. 抽象地考虑它(双关语意)使这些概念难以掌握。

Once you are in one part of your codebase where you want to send a message but do not care if it goes out by email or SMS , then you will see the wisdom of having a Message interface with concrete classes EmailMessage & SmsMessage . 一旦您进入了代码库的某个部分,希望在其中发送消息,而不管消息是否通过电子邮件或SMS发送出去,那么您将发现拥有一个包含具体类EmailMessageSmsMessageMessage接口的智慧。 The part of the code composing the message needs only the interface methods, while the part of the code actually sending the message on its way will need the concrete classes. 组成消息的代码部分仅需要接口方法,而实际上按其方式发送消息的代码部分将需要具体的类。

When you are handling mail order fulfillment, and get your first international mail with special needs such as Customs Declaration, then you will see the need for a MailOrder interface with concrete classes for DomesticMailOrder & InternationalMailOrder . 当您处理邮件订单履行时,并收到第一份有特殊需要的国际邮件(如海关申报单)时,您将看到需要MailOrder接口以及具体的DomesticMailOrderInternationalMailOrder类的接口。 The part of your app listing orders for a manager to view needs only the methods on the interface such as getDollarValue while the part of your app responsible for shipping will need the different behaviors provided by the concrete classes. 您的应用程序列出订单供管理者查看的部分仅需要界面上的方法(例如getDollarValue而负责运输的应用程序部分则需要具体类提供的不同行为。

See also Wikipedia for Abstract and concrete and Class (computer programming) . 另请参见Wikipedia,以了解抽象,具体类(计算机编程)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM