我们假设我有3个班级:Car
,Convertible
和Garage
。
Car
是Convertible
继承自的抽象类:
Convertible有一个名为unfoldRoof()
的特定方法。
Garage
包含一个Car
,其中包含以下getCar()
方法:
public Car getCar() {
return car;
}
通过getter访问Car
属性时,我无法使用特定的Convertible
方法unfoldRoof()
。
如何构建一个泛型 getter,它返回子类而不是抽象父类?
答案 0 :(得分:1)
通用界面中的特定于运行时的类型
您可以指定一般的扩展返回类型
public abstract Car <CarType extends Car>{
public abstract CarType getTypedCar();
}
......然后......
public class Convertable extends Car<Convertable> {
public <Convertable> getTypedCar(){
return this;
}
}
但是当你做getTypedCar()
时,你仍然需要知道你得到了什么类型。
Convertable convertable = car.getTypedCar();
并且它会是相同的(就运行时类型的安全性而言)并不是因为它没有产生并且写作
Convertable convertable = (Convertable)car;
容器保存接口实例的运行时特定类型
如果您希望Garage
知道其持有的Car
的运行时类型,则会出现此问题。您希望它保留任何Car
但您希望它在运行时返回特定类型,它在编译时不知道所以只能定义为返回特定于它的对象持有;在这种情况下,Car
。
你可以通过让Garage
只保持Convertables
像@Valentin Ruano建议来解决这个问题,但在现实生活中,这是一个愚蠢的想法,因为你的对象不能代表现实世界的对象他们应该这样做。也就是说你可以建造一个只需要敞篷车的车库吗?!
您的需求
这完全取决于您的需求。例如,您是否需要知道汽车从Garage
中删除它的类型?或者您可以返回Car
然后使用上面的解决方案来getTypedCar()
吗?同样,您需要知道(假设)要执行此操作的汽车类型,但为了灵活,需要在此设计中进行此操作。
这个假设的另一个地方是Garage
的吸气剂,你可以有一个方法getCar(Class carType)
并且如果所需的车型不是&#39则让它抛出NoSuchCarException
; t,否则返回carType
的类型。
答案 1 :(得分:1)
这是一项功能,因此请使用可选:
public virtual void Delete(Expression<Func<T,bool>> predicate)
{
var query = Context.Set<T>().Where(predicate);
Context.Set<T>().RemoveRange(query);
}
顺便说一下。一般中的继承Car / Convertible 不是真的需要,你可以有像
这样的接口class Car {
<C extends Car> Optional<C> as(Class<C> type) {
return type.isInstance(this)
? Optional.of(type.cast(this))
: Optional.empty();
}
}
Car car = new Convertible();
car.as(Convertible.class).ifPresent(convertible -> {
convertible.unfoldRoof();
});
但是,这需要在地图字段等中安装功能/功能。
答案 2 :(得分:0)
你可以为刚刚返回的汽车定义unfoldRoof(),什么都不做。
答案 3 :(得分:0)
最优雅的解决方案是使abstract class Car {
String make();
int year();
//...
}
class Convertible extends Car {
void unfoldRoof() { /* whatever */ }
}
class Garage<C extends Car> {
private C car = null;
public Garage() {}
public boolean isEmpty() { return car == null; }
public C getCar() { return car; }
public void park(final C car) {
if (!isEmpty()) {
throw new IllegalStateException("Garage is full!!");
} else {
this.car = car;
}
}
public C exit() {
if (isEmpty()) {
throw new IllegalArgumentException("There is no cars in garage");
} else {
final C exitingCar = car;
car = null;
return exitingCar;
}
}
}
class Main {
public static void main(String[] args) {
final Garage<Convertible> myGarage = new Garage();
final Convertible car = ...;
myGarage.park(car);
//...
car = myGarage.getCar();
car.unfoldRoof();
}
}
通用:
import json
import webbrowser
from hashlib import md5
import urllib3
class PyLast():
def __init__(self, API_KEY, SECRET, SESSION_KEY=None):
self.__API_KEY__ = API_KEY
self.__SECRET__ = SECRET
self.__SESSION_KEY__ = SESSION_KEY
self.__api_signature__ = None
if SESSION_KEY is None:
self.__is_authorized__ = False
else:
self.__is_authorized__ = True
self.__http__ = urllib3.PoolManager()
def request_token(self):
print("Getting the token...")
url = 'http://ws.audioscrobbler.com/2.0/?method=auth.gettoken&api_key={}&format=json'.format(self.__API_KEY__)
req_response = self.__http__.request('GET', url, headers={'User-Agent' : 'Mozilla/5.0'})
if req_response.status == 200:
json_data = json.loads(req_response.data.decode('utf-8'))
TOKEN = json_data['token']
self.__TOKEN__ = TOKEN
return TOKEN
else:
print("Error with code " + req_response.status)
def authorize(self):
if not self.__is_authorized__:
url = 'http://www.last.fm/api/auth/?api_key={}&token={}'.format(self.__API_KEY__, self.__TOKEN__)
# open browser to authorize app
webbrowser.open(url, new=0, autoraise=True)
# Make sure authorized
self.__is_authorized__ = True
def start_session(self):
if self.__is_authorized__:
data = "api_key{}methodauth.getSessiontoken{}{}" \
.format(self.__API_KEY__, self.__TOKEN__, self.__SECRET__).encode(
encoding='utf-8')
self.__api_signature__ = md5(data).hexdigest()
url = 'http://ws.audioscrobbler.com/2.0/?method=auth.getSession&api_key={}&token={}&api_sig={}&format=json'.format(
self.__API_KEY__, self.__TOKEN__, self.__api_signature__)
req_response = self.__http__.request('GET', url)
if req_response.status == 200:
json_data = json.loads(req_response.data.decode('utf-8'))
session_key = json_data['session']['key']
self.__SESSION_KEY__ = session_key
url = 'http://ws.audioscrobbler.com/2.0/?method=track.love&api_key={}&api_sig={}&sk={}&artist=cher&track=believe&format=json'.format(
self.__API_KEY__, self.__api_signature__, self.__SESSION_KEY__)
req_response = self.__http__.request('POST', url)
return self.__SESSION_KEY__
else:
print("Error with code " + str(req_response.status))
else:
print("Not authorized!")