在Typescript中,有一个多态返回类型this
的概念。
https://www.typescriptlang.org/docs/handbook/advanced-types.html#polymorphic-this-types
示例:
export abstract class Animal {
private name: string;
public setName(name: string): this {
this.name = name;
return this;
}
}
export class Dog extends Animal {
private breed: string;
public setBreed(breed: string): this {
this.breed = breed;
return this;
}
}
export class FluffyDog extends Dog {
private fluffiness: number;
public setFluffiness(fluffiness: number): this {
this.fluffiness = fluffiness;
return this;
}
}
export class Main {
constructor() {
const dog: FluffyDog = new FluffyDog()
.setName('Fluffy')
.setFluffiness(10)
.setBreed('Lab');
}
}
Java中是否有等效的东西? 我想出的最好的方法是:
public abstract class Animal<T extends Animal<T>> {
private String name;
public T setName(String name) {
this.name = name;
return (T)this;
}
}
class Dog extends Animal<Dog> {
private String breed;
public Dog setBreed(String breed) {
this.breed = breed;
return this;
}
}
class Main {
static {
Dog dog = new Dog()
.setName("Fluffy")
.setBreed("Lab");
}
}
或者这个:
public abstract class Animal {
private String name;
public <T extends Animal> T setName(String name) {
this.name = name;
return (T)this;
}
}
class Dog extends Animal {
private String breed;
public <T extends Dog> T setBreed(String breed) {
this.breed = breed;
return (T)this;
}
}
class FluffyDog extends Dog {
private Long fluffiness;
public <T extends FluffyDog> T setFluffiness(Long fluffiness) {
this.fluffiness = fluffiness;
return (T)this;
}
}
class Main {
static {
FluffyDog dog = new FluffyDog()
.<FluffyDog>setName("Fluffy")
.setFluffiness(10L)
.setBreed("Lab");
}
}
第一个似乎只能被继承一次。
第二种方法在某些情况下需要显式类型参数。
在Java中有什么方法可以返回多态吗?
答案 0 :(得分:3)
另外两个选项:
由于设置方法的顺序无关紧要,功能上,请按自下而上的顺序进行调用。如果先分配变量,则无需强制转换。
final FluffyDog dog = new FluffyDog();
dog.setFluffiness(10)
.setBreed("Lab")
.setName("Fluffy");
使用super
委派给实际的实现,重写继承的setter方法以更改返回类型:
class Animal {
private String name;
public Animal setName(String name) {
this.name = name;
return this;
}
}
class Dog extends Animal {
private String breed;
@Override
public Dog setName(String name) {
super.setName(name);
return this;
}
public Dog setBreed(String breed) {
this.breed = breed;
return this;
}
}
class FluffyDog extends Dog {
private long fluffiness;
@Override
public FluffyDog setName(String name) {
super.setName(name);
return this;
}
@Override
public FluffyDog setBreed(String breed) {
super.setBreed(breed);
return this;
}
public FluffyDog setFluffiness(long fluffiness) {
this.fluffiness = fluffiness;
return this;
}
}
class Main {
public static void main(String[] args) throws Exception {
final FluffyDog dog = new FluffyDog()
.setName("Fluffy")
.setBreed("Lab")
.setFluffiness(10);
}
}
答案 1 :(得分:1)
使用第一个替代方法,您仍然可以进行两个继承级别。诚然,它不是很容易理解。不幸的是,泛型是在1.5中添加的Java附加功能,并且许多Java Bean模式都不适合这些链接方法。 (您会注意到,大多数setter方法在传统的Java类中都返回void
)。
public abstract class Animal<T extends Animal<T>> {
private String name;
public T setName(String name) {
this.name = name;
return (T)this;
}
}
public class Dog<T extends Dog<T>> extends Animal<T> {
private String breed;
public T setBreed(String breed) {
this.breed = breed;
return (T) this;
}
}
public class FluffyDog extends Dog<FluffyDog> {
private Long fluffiness;
public <T extends FluffyDog> T setFluffiness(Long fluffiness) {
this.fluffiness = fluffiness;
return (T) this;
}
}
如果您想允许FluffyDog
被覆盖并提供相同的模式,那么您将不得不像Dog
类中那样使用通用类型再次做同样的事情。