题
我试图用java包围我的想法。当我将一个对象传递给另一个类的方法时,我不能只调用该对象类固有的任何方法吗?
如下例所示的代码无法编译的原因是什么?
谢谢,
class a {
public static void myMethod(Object myObj) {
myObj.testing();
}
}
class b {
public void testing() {
System.out.println ("TESTING!!!");
}
}
class c {
public static void main (String[] args) {
b myB = new b();
a.myMethod(myB);
}
}
编辑:我将myMethod中的参数保留为Object类型的原因是因为我希望能够传递各种对象类型,每种类型都有一个testing()方法。
解决方案
如果您想使用 testing()
方法传递各种对象,请让每个对象实现 Testable
接口:
public interface Testable
{
public void testing()
}
然后让 myMethod()
获取 Testable
。
public static void myMethod(Testable testable)
{
testable.testing();
}
编辑:为了澄清,实现一个接口意味着该类保证拥有该方法,但该方法可以做任何想做的事情。所以我可以有两个类 testing()
方法做不同的事情。
public class AClass implements Testable
{
public void testing()
{
System.out.println("Hello world");
}
}
public class BClass implements Testable
{
public void testing()
{
System.out.println("Hello underworld");
}
}
其他提示
问题是 myMethod
无法知道它在实际运行之前获取 b
对象。您可以传入 String
,因为它知道。
将其更改为
public static void myMethod(b myObj) {
myObj.testing();
}
它应该有用。
更新问题:
编辑:我将myMethod中的参数保留为Object类型的原因是因为我希望能够传递各种对象类型,每种类型都有一个testing()方法。
正如Amanda S和其他几位人士所说,这是一个完美的界面案例。这样做的方法是创建一个定义 testing()
方法的接口,并更改 myMethod
以获取实现该接口的对象。
另一种解决方案(没有接口)将反射性地发现对象是否具有 testing()
方法并调用它,但不推荐这样做,并且对于这样一个简单的情况不需要。
你所说的是鸭子打字。 Java没有鸭子打字。
因此,您需要定义一个接口,使用 testing()
方法实现所有类。
e.g:
public interface Testable
{
public void testing()
}
class B implements Testable
{
public void testing() {
System.out.println ("TESTING!!!");
}
}
class A {
public static void myMethod(Testable myObj) {
myObj.testing();
}
}
您的问题是支持接口的经典论据。您希望尽可能通用,但是您希望传递的每个对象都有一个testing()方法。我建议采取以下措辞:
public interface Testable
{
public void testing();
}
public class A
{
public static void myMethod(Testable myObj)
{
myObj.testing();
}
}
public class B implements Testable
{
public void testing()
{
System.out.println("This is class B");
}
}
public class C implements Testable
{
public void testing()
{
System.out.println("This is class C");
}
}
public class Test
{
public static void main (String[] args)
{
B myB = new B();
C myC = new C();
A.myMethod(myB); // "This is class B"
A.myMethod(myC); // "This is class C"
}
}
因为你传入一个Object(b继承自Object)。对象没有测试,b确实。
您可以在调用方法之前传入b或将对象强制转换为b。
EDIT 传入一个实现该方法的泛型类:您需要创建一个具有方法签名的接口,并传入接口类型而不是Object。您传入的所有对象都必须实现该接口。
您只能访问对象所具有的引用类型可见的成员。
对于 myMethod(Object myObj)
,只表示在Object中定义的成员,所以在 class a
中 class b
的成员>将不可见。
如果您将 a.myMethod
的定义更改为 public static void myMethod(b myObj)
,那么您将能够看到 testing 在
myMethod
中的 b
实例上的code>方法。
根据说明进行更新:
在这种情况下,为所有人实现定义接口可能就是你想要的。
public interface Testable {
public void testing();
}
public class a {
public static void myMethod(Testable myObj) {
myObj.testing();
}
}
public class b implements Testable {
public void testing () {
System.out.println("TESTING!!!");
}
}
为什么java会找到我的方法?
由于Java的设计方式。
Java是“静态类型”,表示在期间检查对象类型汇编。
在Java中,只有当该方法属于该类型时,才能调用方法。
由于此验证是在编译期间进行的,因此对象类型没有“testing()”。方法,编译失败(即使在运行时,对象确实有该方法)。这主要是为了安全。
其他人描述的变通方法将要求您创建一个新类型,您可以在其中告诉编译器
"嘿,此类的实例将响应测试方法“
如果你想传递各种对象并保持它非常通用,一种方法是让这些对象实现和接口。
public interface Testable {
public void testing();
}
class A implements Testable { // here this class commits to respond to "testing" message
public void testing() {
}
}
class B implements Testable { // B "is" testable
public void testing() {
System.out.println("Testing from b");
}
}
class C implements Testable { // C is... etc.
public void testing() {
//....
}
}
稍后其他地方
public void doTest( Testable object ) {
object.testing();
}
doTest( new A() );
doTest( new B() );
doTest( new C() );
“其他”这样做的方法,在java中调用反思的方法但是我不确定这是否是你所需要的,因为当你这样做时,代码会更加抽象,但这就是自动化测试框架(以及许多其他框架,如Hibernate)实际上是如何工作的。
我希望这有助于您澄清原因。
如果你真的,真的想让参数尽可能保持抽象,你应该考虑反射API。这样,您可以传递任何您想要的对象并动态执行您想要的方法。您可以查看一些示例。
这不是唯一的方法,但根据您的问题,它可能是一个有效的选择。
请记住,反射比直接调用方法要慢。您也可以考虑使用界面,例如Amanda的帖子。