简体   繁体   English

有关多态性的Java接口问题

[英]Java Interface question regarding polymorphism

So I have this: 所以我有这个:

interface C {
    void shutUp();
}

class A {
    public void speak() {
       System.out.println("Class a");
    }
}

class B extends A implements C {
    public void shutUp() {
        System.out.println("Saying nothing...");
    }

    public void speak() {
        System.out.println("Class B");
    }
}

If I do this, it works: 如果我这样做,它将起作用:

A obj = new B();
obj.speak()

But I can't do obj.shutUp() Why not? 但是我不能做obj.shutUp()为什么不呢? I have a feeling that I am just confused on something very basic. 我觉得我对一些非常基本的东西感到困惑。

Thanks! 谢谢!

A's static type is not connected to C, thus you cannot do this command, it would be the same to do: A的静态类型未连接到C,因此您无法执行此命令,这将是相同的:

A obj = new A();
obj.shutUp();

(which is obviously illegal..) (这显然是非法的。)
the only one who can use both is B 唯一可以同时使用两者的人是B

B obj = new B();
obj.shutUp();
obj.speak();

this is all connected to the fact that Java is static typing 这都与Java是static typing这一事实有关

Because A is not a C - it does not implement the interface - and you can't instantiate an interface that way, because there is no default constructor. 因为A不是C-它没有实现接口-并且您不能以这种方式实例化接口,因为没有默认的构造函数。

A reference of type A doesn't have a method shutUp() , so it's no surprise that it doesn't work. 类型A的引用没有方法shutUp() ,因此它不起作用也就不足为奇了。

And your code uses incorrect keywords: it's class and interface for Java. 而且您的代码使用了错误的关键字:这是Java的classinterface Case matters. 案件很重要。

By saying A obj = new B(); 通过说A obj = new B(); you are decouple your code from a specific implementation of the interface. 您正在将代码与接口的特定实现分离。 So obj will not have access to shutup() function, which was implemented in class b. 因此,obj将无法访问在类b中实现的shutup()函数。

您的obj具有类A接口,因为它是变量的类型。

The type of obj is defined as A ; obj的类型定义为A therefore, obj can only use members that are available to A . 因此, obj只能使用A可用的成员。 Because C inherits from A , C has all the members required to be considered a form of A , which is why it allows you to create a new C in an A variable. 因为C继承自A ,所以C具有被视为A形式的所有成员,这就是为什么它允许您在A变量中创建新C的原因。 Only by casting it to type C can you use all of the members that belong to C . 只有将其强制转换为C类型,您才能使用属于C所有成员。

In your question is mistake: You can't create C object because it's interface - so I think you want create B object, then: 您的问题是错误的:您无法创建C对象,因为它是接口-所以我认为您想创建B对象,然后:

This is because obj is A not C, to use shutUp method you can: 这是因为obj是A而不是C,要使用shutUp方法,您可以:

((C) obj).shutUp() // cast to C type
((B) obj).shutUp() // cast to B type

Or declare: 或声明:

B obj = new B();
obj.shutUp();

Or: 要么:

C obj = new B(); // (!) but: you can't (without casting) call speak method
obj.shutUp();

A obj = new C(); obj =新的C();

as C is interface, u cant create instance of interface. 因为C是接口,所以您不能创建接口的实例。 Please correct the question. 请更正问题。

the reason to why you can't call shutUp on obj is this: 为什么不能在obj上调用shutUp的原因是:

obj is not an object, it's a pointer or reference. obj不是对象,而是指针或引用。 the object you create when you do new B() is one thing, obj (or "how you use the object") is a separate thing. 执行新B()时创建的对象是一回事,obj(或“如何使用该对象”)是另一回事。 you use the object with the help of a reference (in this case obj), which lets you access different sides of the actual object. 您可以在引用(在本例中为obj)的帮助下使用对象,该引用使您可以访问实际对象的不同侧面。

if the reference you use to access the object is of the type that references the object at hand (ie has the same name) then you can access the whole object through this reference. 如果用于访问对象的引用是引用当前对象的类型(即,具有相同的名称),则可以通过此引用访问整个对象。 otherwise you can only access those parts of the object that the reference type can see. 否则,您只能访问引用类型可以看到的对象部分。

in your example, the reference type is A, ie obj sees only the A part of whatever object it's referring to. 在您的示例中,引用类型为A,即obj仅看到其引用的任何对象的A部分。 therefore it can't access the B/C part of the object, event though the object has these behaviors. 因此,即使对象具有这些行为,它也无法访问对象的B / C部分。

Other people have answered this already, but do note that there is a way to call shutUp() without casting to B or C : 其他人已经回答了这个问题,但是请注意,有一种方法可以在不强制转换为BC情况下调用shutUp()

A obj = new B();
try {
    Method shutUp = obj.getClass().getMethod("shutUp", null);
    shutUp.invoke(obj, null);
}
catch (Exception ignored) {}
A obj = new B();

Here you are creating an instance of "B" which is of type "A". 在这里,您将创建类型为“ A”的“ B”实例。 ie you are saying "I want to make an object B and name it obj which is of type A". 即,您说的是“我想创建一个对象B并将其命名为类型A的obj”。

In class A there is only one method which is accessible. 在A类中,只有一种可访问的方法。 It did not implement C 它没有实现C

public void speak() {}

To be able to access all the methods of class B, you should create an instance of "B" of type "B" 为了能够访问类B的所有方法,您应该创建“ B”类型的“ B”实例

B obj2 = new B();

This way you will be able to access 这样您就可以访问

 public void shutUp() {}

This is because it is B which implements class "C". 这是因为实现类“ C”的是B。

One way to be able to access both methods using "obj" is to make A implement C 能够使用“ obj”访问这两种方法的一种方法是使A工具C

Object created by new B() can be used as an object of either of three types — A, B or C. But you can't declare a variable of several types. new B()创建的对象可用作三种类型的对象-A,B或C。但是您不能声明多种类型的变量。

Since B is a subtype of A and C you can use its instance as an instance of any of those types. 由于B是A和C的子类型,因此您可以将其实例用作任何这些类型的实例。 Eg 例如

B o = new B();
A aO = o;
C cO = o;

Now you can use o to access both speak and shutUp methods, you can use aO to access speak method and cO to access shutUp method. 现在你可以使用o来访问speakshutUp方法,您可以使用aO访问speak方法和cO访问shutUp方法。 It doesn't matter which variable you will use the methods called will be the same because those variables all reference the same object. 不管使用哪个变量,调用的方法都是相同的,因为这些变量都引用相同的对象。 Why you can't use aO to invoke shutUp in Java is because you have declared your variable with a type that doesn't have such a method. 为什么不能使用aO来调用Java中的shutUp原因是因为您使用没有这种方法的类型声明了变量。 Although you know that this particular object does have that method doesn't make it so in general. 尽管您知道该特定对象确实具有该方法,但一般而言并非如此。

class D extends A {
    public void speak(){
        System.out.println("Class D");
    }
}

List<A> as = new ArrayList<A>();
as.add(new A());
as.add(new B());
as.add(new D());

A a0 = as.get(0);
A a1 = as.get(1);
A a2 = as.get(2);

a0.speak(); // >> Class A
a1.speak(); // >> Class B
a2.speak(); // >> Class D 

Now, in this example you have instances of three different classes in a single collection. 现在,在此示例中,单个集合中包含三个不同类的实例。 When you pass this collection around or modify it you will never know which class is each object actually is. 当您传递或修改此集合时,您将永远不知道每个对象实际上是哪个类。 All you know is that they all are of type A, they are guaranteed to be of that type though actually they can be of any subtype of A (like B or D). 您所知道的都是它们都是A类型的,尽管实际上它们可以是A的任何子类型(例如B或D),但它们一定是该类型的。

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

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