无法从接口调用抽象 class 方法
Unable to call abstract class method from interface
我很难掌握针对接口编程的概念并同时使用抽象 classes。
我有一组 "Retriever" classes 可以从 Internet 检索不同类型的数据。这些检索器 classes 检索 JSON 响应的字符串
public class AccountRetriever extends DataRetriever implements AccountInformation{
List<String> getAccountInformation{
....
}
}
public class BalanceRetriever extends DataRetriever implements BalanceInformation{
List<String> getBalanceInformation{
....
}
}
AccountInformation 和 BalanceInformation 都是具有其中显示的方法的接口。我还从抽象 class "DataRetriever" 扩展,它有一个名为
的方法
public String getResponseAsString();
在我的主要使用接口中实例化这些 classes 之后:
AccountInformation ai = new AccountRetriever(apiRequest);
List<String> aiList = ai.getAccountInformation(); <----this works
ai.getResponseAsString(); <----this doesn't work. Why??
BalanceInformation bi = new BalanceRetriever(apiRequest);
List<String> biList = bi.getBalanceInformation(); <----this works
bi.getResponseAsString(); <----this doesn't work. Why??
getResponseAsString() 方法存在于摘要中 class 这些检索器中的每一个都扩展自,那么为什么我无法访问该方法?我可以访问的唯一方法是界面中的方法。我在这里做错了什么?
这些方法不可见,因为当你构造一个 AccountRetriever
时,你的 ai
变量只是类型 AccountInformation
,只有 getAccountInformation()
的接口没有getResponseAsString()
AccountInformation ai = new AccountRetriever(apiRequest);
List<String> aiList = ai.getAccountInformation(); <----this works
ai.getResponseAsString(); <----this doesn't work. Why??
但是如果您将变量类型更改为 DataRetriever
,则 getAccountInformation()
将可见,但 getAccountInformation()
将不可见。
DataRetriever ai = new AccountRetriever(apiRequest);
List<String> aiList = ai.getAccountInformation(); <----this wont work
ai.getResponseAsString(); <---- this will work
您需要将变量类型更改为 AccountRetriever
,它既扩展了 DataRetriever
又实现了 AccountInformation
AccountRetriever ai = new AccountRetriever(apiRequest);
List<String> aiList = ai.getAccountInformation(); <----this will work
ai.getResponseAsString(); <---- this will work
或者,更改您的设计,使 AccountInformation
和 BalanceInformation
都扩展定义 getResponseAsString()
的通用接口。并一起删除摘要 class 。
public interface Information {
public String getResponseAsString();
}
public interface AccountInformation extends Information {
public List<String> getAccountInformation();
}
public interface BalanceInformation extends Information {
public List<String> getBalanceInformation();
}
你的是多重继承的一个例子。
AccountRetriever IS-A AccountInformation (实现接口)
AccountRetriever IS-A DataRetriever (扩展摘要 class)
因此 AccountRetriever 引用 可以使用 AccountInformation 和 [=27= 的方法]DataRetriever.
// Will work
AccountRetriever ar = new AccountRetriever(apiRequest);
List<String> arList = ar.getAccountInformation();
ar.getResponseAsString();
但是 没有 IS-A AccountInformation 之间的关系 和 DataRetriever.
因此 AccountInformation 引用 不能使用 DataRetriever 的方法,即使它可能包含 AccountRetriever 实例(通过向上转换).
// Won't Work
AccountInformation ai = new AccountRetriever(apiRequest); //upcasting
ai.getResponseAsString(); //error
同样的逻辑适用于 BalanceRetriever, BalanceInformation 和 DataRetriever。
// Will work
BalanceRetriever br = new BalanceRetriever(apiRequest);
List<String> brList = br.getBalanceInformation();
br.getResponseAsString();
// Won't work
BalanceInformation bi = new BalanceRetriever(apiRequest); //upcasting
bi.getResponseAsString(); //error
您的问题本质上与我们收到很多问题的一个简单得多的问题相同。像这样:
class Animal { ... }
class Dog extends Animal {
public void bark() { ... } // new method not inherited from Animal
}
Animal a = new Dog();
a.bark(); // ILLEGAL
新手程序员搞不懂为什么 a.bark()
不合法。答案当然是当编译器看到a.bark()
时,它只知道a
是一个Animal
,所以不能确定a
有一个bark
方法。 a
允许的唯一方法是为 Animal
定义的方法。不允许知道 a
是一个 Dog
--只能在 运行 时间检查。
你的问题是一样的,虽然它涉及更多的复杂性。
AccountInformation ai = new AccountRetriever(apiRequest);
ai.getResponseAsString(); <----this doesn't work. Why??
ai
声明为 AccountInformation
;因此,唯一可以在其上使用的方法是为 AccountInformation
接口声明的方法。毕竟,您 可以 声明另一个实现 AccountInformation
但不扩展 DataRetriever
的 class,并且 ai
可以是一个对象class,在这种情况下,将没有 getResponseString
方法。
请注意,如果您有一个 AccountInformation
对象并且您确定它也是一个 DataRetriever
,您可以转换为它。
public void someMethod(ai: AccountInformation) {
((DataRetriever)ai).getResponseAsString(); // LEGAL
这将在 运行 时间检查 ai
是否是扩展 DataRetriever
的某些 class 的成员,如果不是则抛出异常。
我很难掌握针对接口编程的概念并同时使用抽象 classes。
我有一组 "Retriever" classes 可以从 Internet 检索不同类型的数据。这些检索器 classes 检索 JSON 响应的字符串
public class AccountRetriever extends DataRetriever implements AccountInformation{
List<String> getAccountInformation{
....
}
}
public class BalanceRetriever extends DataRetriever implements BalanceInformation{
List<String> getBalanceInformation{
....
}
}
AccountInformation 和 BalanceInformation 都是具有其中显示的方法的接口。我还从抽象 class "DataRetriever" 扩展,它有一个名为
的方法public String getResponseAsString();
在我的主要使用接口中实例化这些 classes 之后:
AccountInformation ai = new AccountRetriever(apiRequest);
List<String> aiList = ai.getAccountInformation(); <----this works
ai.getResponseAsString(); <----this doesn't work. Why??
BalanceInformation bi = new BalanceRetriever(apiRequest);
List<String> biList = bi.getBalanceInformation(); <----this works
bi.getResponseAsString(); <----this doesn't work. Why??
getResponseAsString() 方法存在于摘要中 class 这些检索器中的每一个都扩展自,那么为什么我无法访问该方法?我可以访问的唯一方法是界面中的方法。我在这里做错了什么?
这些方法不可见,因为当你构造一个 AccountRetriever
时,你的 ai
变量只是类型 AccountInformation
,只有 getAccountInformation()
的接口没有getResponseAsString()
AccountInformation ai = new AccountRetriever(apiRequest);
List<String> aiList = ai.getAccountInformation(); <----this works
ai.getResponseAsString(); <----this doesn't work. Why??
但是如果您将变量类型更改为 DataRetriever
,则 getAccountInformation()
将可见,但 getAccountInformation()
将不可见。
DataRetriever ai = new AccountRetriever(apiRequest);
List<String> aiList = ai.getAccountInformation(); <----this wont work
ai.getResponseAsString(); <---- this will work
您需要将变量类型更改为 AccountRetriever
,它既扩展了 DataRetriever
又实现了 AccountInformation
AccountRetriever ai = new AccountRetriever(apiRequest);
List<String> aiList = ai.getAccountInformation(); <----this will work
ai.getResponseAsString(); <---- this will work
或者,更改您的设计,使 AccountInformation
和 BalanceInformation
都扩展定义 getResponseAsString()
的通用接口。并一起删除摘要 class 。
public interface Information {
public String getResponseAsString();
}
public interface AccountInformation extends Information {
public List<String> getAccountInformation();
}
public interface BalanceInformation extends Information {
public List<String> getBalanceInformation();
}
你的是多重继承的一个例子。
AccountRetriever IS-A AccountInformation (实现接口)
AccountRetriever IS-A DataRetriever (扩展摘要 class)
因此 AccountRetriever 引用 可以使用 AccountInformation 和 [=27= 的方法]DataRetriever.
// Will work
AccountRetriever ar = new AccountRetriever(apiRequest);
List<String> arList = ar.getAccountInformation();
ar.getResponseAsString();
但是 没有 IS-A AccountInformation 之间的关系 和 DataRetriever.
因此 AccountInformation 引用 不能使用 DataRetriever 的方法,即使它可能包含 AccountRetriever 实例(通过向上转换).
// Won't Work
AccountInformation ai = new AccountRetriever(apiRequest); //upcasting
ai.getResponseAsString(); //error
同样的逻辑适用于 BalanceRetriever, BalanceInformation 和 DataRetriever。
// Will work
BalanceRetriever br = new BalanceRetriever(apiRequest);
List<String> brList = br.getBalanceInformation();
br.getResponseAsString();
// Won't work
BalanceInformation bi = new BalanceRetriever(apiRequest); //upcasting
bi.getResponseAsString(); //error
您的问题本质上与我们收到很多问题的一个简单得多的问题相同。像这样:
class Animal { ... }
class Dog extends Animal {
public void bark() { ... } // new method not inherited from Animal
}
Animal a = new Dog();
a.bark(); // ILLEGAL
新手程序员搞不懂为什么 a.bark()
不合法。答案当然是当编译器看到a.bark()
时,它只知道a
是一个Animal
,所以不能确定a
有一个bark
方法。 a
允许的唯一方法是为 Animal
定义的方法。不允许知道 a
是一个 Dog
--只能在 运行 时间检查。
你的问题是一样的,虽然它涉及更多的复杂性。
AccountInformation ai = new AccountRetriever(apiRequest);
ai.getResponseAsString(); <----this doesn't work. Why??
ai
声明为 AccountInformation
;因此,唯一可以在其上使用的方法是为 AccountInformation
接口声明的方法。毕竟,您 可以 声明另一个实现 AccountInformation
但不扩展 DataRetriever
的 class,并且 ai
可以是一个对象class,在这种情况下,将没有 getResponseString
方法。
请注意,如果您有一个 AccountInformation
对象并且您确定它也是一个 DataRetriever
,您可以转换为它。
public void someMethod(ai: AccountInformation) {
((DataRetriever)ai).getResponseAsString(); // LEGAL
这将在 运行 时间检查 ai
是否是扩展 DataRetriever
的某些 class 的成员,如果不是则抛出异常。