I know that it is possible to define static methods in Java interfaces that are bound to the interface itself. However, I would like to define the signature of a static method to be implemented by the class that implements the interface. This would allow to use the design pattern called Static Creation Method.
I cannot define a static method in the interface because the implementation depends on the concrete class. Also, I can not just pretend that my classes will have the Static Creation Method, because I want to call the method recursively as in the Rust example that comes next.
I can do this in 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() }
}
}
Do you know if there is a way to do something similar in Java? Is there a better way to provide similar functionality? Is there a reason for Java avoiding this kind of implementation, or is it just bad language design?