我正在开发一个符合我需求的线性代数库。目前我有2个想法,但我想知道这两个结构的优点和缺点是做出好的选择。
例如使用向量:
//First structure (simple inheritance using generics
//to prevent instanceof and casting in subclasses
public abstract class AbstractVector<T>{
public abstract T method(T t){...}
...
}
public class Vector2 extends AbstractVector<Vector2>{
public Vector2(){...}
//Implements AbstractVector method, generic T is Vector2
public Vector2 method(Vector2 vector){...}
}
public class Vector3 extends AbstractVector<Vector3>{...}
public class Vector4 extends AbstractVector<Vector4>{...}
//Second structure (using the structure of java AbstractList/List/ArrayList
//prevents instanceof and casting in subclasses )
public interface Vector<T>{
T method(T t){...}
}
public abstract class AbstractVector<T> implements Vector<T>{...}
public class Vector2 extends AbstractVector<Vector2>{
public Vector2(){...}
//Implements Vector interface method, generic T is Vector2
public Vector2 method(Vector2 vector){...}
}
public class Vector3 extends AbstractVector<Vector3>{...}
public class Vector4 extends AbstractVector<Vector4>{...}
就使用而言:
//1st structure
Vector2 vector2 = new Vector2();
Vector3 vector3 = new Vector3();
vector2.method(vector3) //Compile time error!
//2nd structure (I use Vector type main advantage of interface)
Vector vector2 = new Vector2();
Vector vector3 = new Vector3();
vector2.method(vector3) //Runtime error!
目前我有以下优点和缺点:
Vector
我是否错过了使一个结构超过另一个结构的优点/缺点?
编辑:这个库的主要目的是将它用于几何定义和openGL渲染。
答案 0 :(得分:1)
我明白你的意图。您希望使向量的维度成为编译时常量,并让编译器在维度适合时检入操作(如加法,标量乘法)。我过去曾经想过这些事情,但我无法找到一个好的解决方案。类型可以通过其他类型进行参数化,但不能通过数字进行参数化。
我的建议是摆脱类型定义中的所有数字。只需使用字段Vector
定义一个类dimension
即可。然后,您可以检查每个操作的维度兼容性,只获得一个类(而不是n个不同的类)。这对于测试和维护代码来说是一个巨大的好处。缺点是维度问题导致运行时异常而不是编译问题。但是拥有清晰整洁的代码比这更重要。
答案 1 :(得分:1)
拥有Set
接口和单独的实现类HashSet
,TreeSet
的原因是天真的。 它使所有代码尽可能通用,并使继承变得简单。它允许在将来扩展API,具有向后兼容性(对于其他类)。
还有一个Set
具有特殊功能的问题:SortedSet
界面扩展Set
并且仅由TreeSet
实施。
interface Vector {
}
class SparseVector implements Vector {
}
class UnitVector implements Vector {
}
interface IonicalVector extends Vector {
IonicalVector rotate(double phi);
}
class QuatrionsVector implements IonicalVector {
@Override
public IonicalVector rotate(double phi) { ... }
}
缺点是LinkedList
的{{1}}中的开销不适合它。
就个人而言,我会继续使用简单的类,并且当可以想到不同的实现时,看看有什么意义。
请注意,您还可以使用builder pattern通过动态选择(私有)实现来实现一个接口。有点像get(int index)
。
Arrays.asList