我无法在接口中定义静态方法,因为实现取决于具体类。另外,我不能假装我的类将具有静态创建方法,因为我想递归地调用该方法,就像接下来的 Rust 示例一样。
我可以用 Rust 做到这一点:
fn main() {
Double::zero().print();
Complex::<Double>::zero().print();
Dual::<Double>::zero().print();
Dual::<Complex::<Double>>::zero().print();
Complex::<Dual::<Double>>::zero().print();
}
trait SetElement<T: SetElement<T>>
{
fn to_string( &self ) -> String;
fn print( &self )
{
println!( "{}" , self.to_string() );
}
}
trait AdditiveUnitalMagma<T: AdditiveUnitalMagma<T>>: SetElement<T>
{
fn zero() -> T;
}
struct Double
{
x: f64,
}
impl SetElement<Double> for Double
{
fn to_string( &self ) -> String
{
self.x.to_string()
}
}
impl AdditiveUnitalMagma<Double> for Double
{
fn zero() -> Double
{
Double{ x: 0.0 }
}
}
struct Complex<T>
{
x: T,
y: T,
}
impl<T: SetElement<T>> SetElement<Complex<T>> for Complex<T>
{
fn to_string( &self ) -> String
{
"(".to_owned() + &self.x.to_string() + ") + i (" + &self.y.to_string() + ")"
}
}
impl<T: AdditiveUnitalMagma<T>> AdditiveUnitalMagma<Complex<T>> for Complex<T>
{
fn zero() -> Complex<T>
{
Complex{ x: T::zero() , y: T::zero() }
}
}
struct Dual<T>
{
a: T,
b: T,
}
impl<T: SetElement<T>> SetElement<Dual<T>> for Dual<T>
{
fn to_string( &self ) -> String
{
"(".to_owned() + &self.a.to_string() + ") + epsilon (" + &self.b.to_string() + ")"
}
}
impl<T: AdditiveUnitalMagma<T>> AdditiveUnitalMagma<Dual<T>> for Dual<T>
{
fn zero() -> Dual<T>
{
Dual{ a: T::zero() , b: T::zero() }
}
}
你知道是否有办法在Java中做类似的事情吗?也就是说,能够递归地使用静态创建方法:
public static void main(String[] args) {
Double.zero().print();
Complex<Double>.zero().print();
Dual<Double>.zero().print();
Dual<Complex<Double>>.zero().print();
Complex<Dual<Double>>.zero().print();
}
有没有更好的方法来提供类似的功能? Java 是否有理由避免这种实现,或者只是糟糕的语言设计?
如果我正确理解你的问题,这通常是使用工厂类而不是静态工厂方法来解决的:
sealed abstract class ValueFactory<T>
permits DoubleFactory,
ComplexFactory,
DualFactory {
abstract T zero();
}
final class DoubleFactory
extends ValueFactory<Double> {
@Override
Double zero() { /* ... */ }
}
final class ComplexFactory<U>
extends ValueFactory<Complex<U>> {
ComplexFactory(Supplier<? extends U> zeroElementCreator) { /* ... */ }
@Override
Complex<U> zero() { /* ... */ }
}
final class DualFactory<U>
extends ValueFactory<Dual<U>> {
DualFactory(Supplier<? extends U> zeroElementCreator) { /* ... */ }
@Override
Dual<U> zero() { /* ... */ }
}