у меня есть такой класс для работы с вектором длиной 3: package com.cgvsu.math;

import java.util.Objects;

// Это заготовка для собственной библиотеки для работы с линейной алгеброй
public class Vector3f extends AbstractVector {
    private float[] components = new float[SIZE];
    private static final int SIZE = 3;

    private float length;

    // Конструкторы + getters and setters
    public Vector3f(float x, float y, float z) {
        this.components[0] = x;
        this.components[1] = y;
        this.components[2] = z;
        calcLength();
    }
    public Vector3f() {
        this.components[0] = 0;
        this.components[1] = 0;
        this.components[2] = 0;
        calcLength();
    }

    public float getX() {
        return components[0];
    }

    public void setX(float x) {
        components[0] = x;
        calcLength();
    }

    public float getY() {
        return components[1];
    }

    public void setY(float y) {
        components[1] = y;
        calcLength();
    }

    public float getZ() {
        return components[2];
    }

    public void setZ(float z) {
        components[2] = z;
        calcLength();
    }

    /**
     * Возвращает компонент вектора по индексу.
     *
     * @param a Индекс компонента (0 для x, 1 для y, 2 для z).
     * @return Значение компонента.
     * @throws IndexOutOfBoundsException если индекс не равен 0, 1 или 2.
     */
    public float getNum(int a) {
        if (a < 0 || a >= components.length) {
            throw new IndexOutOfBoundsException("Invalid index: " + a);
        }
        return components[a];
    }

    /**
     * Заменяет значения для x,y,z по индексу.
     *
     * @param a Индекс компонента (0 для x, 1 для y, 2 для z).
     * @param num Новое число для переменной
     * @throws IndexOutOfBoundsException если индекс не равен 0, 1 или 2.
     */
    public void setNum(int a, float num) {
        if (a < 0 || a >= components.length) {
            throw new IndexOutOfBoundsException("Invalid index: " + a);
        }
        components[a] = num;
    }

    // Метод для вычисления длины вектора
    private void calcLength() {
        length = (float) Math.sqrt(components[0] * components[0]
                + components[1] * components[1]
                + components[2] * components[2]);
    }

    @Override
    public float length() {
        return length;
    }

    // Метод для нормализации вектора
    private void calcNormalize() {
        calcLength();
        if (length == 0) {
            return;
        }
        divide(length);
    }

    @Override
    public void normalize() {
        calcNormalize();
    }

    // Метод сложения векторов
    @Override
    public Vector3f add(AbstractVector other) {
        if (!isVector3f(other)) {
            throw new IllegalArgumentException("Неверный тип вектора для сложения");
        }
        Vector3f o = (Vector3f) other;
        return new Vector3f(
                this.components[0] + o.components[0],
                this.components[1] + o.components[1],
                this.components[2] + o.components[2]
        );
    }

    // Метод вычитания векторов
    @Override
    public Vector3f subtract(AbstractVector other) {
        if (!isVector3f(other)) {
            throw new IllegalArgumentException("Неверный тип вектора для вычитания");
        }
        Vector3f o = (Vector3f) other;
        return new Vector3f(
                this.components[0] - o.components[0],
                this.components[1] - o.components[1],
                this.components[2] - o.components[2]
        );
    }

    // Метод умножения вектора на скаляр
    @Override
    public void multiply(float scalar) {
        for (int i = 0; i < components.length; i++) {
            this.components[i] *= scalar;
        }
        calcLength();
    }

    // Метод деления вектора на скаляр
    @Override
    public void divide(float scalar) {
        if (scalar == 0) throw new ArithmeticException("Деление на ноль");
        for (int i = 0; i < components.length; i++) {
            this.components[i] /= scalar;
        }
        calcLength();
    }

    // Метод скалярного произведения
    @Override
    public float dot(AbstractVector other) {
        if (!isVector3f(other)) {
            throw new IllegalArgumentException("Неверный тип вектора для скалярного произведения");
        }
        Vector3f o = (Vector3f) other;
        return this.components[0] * o.components[0]
                + this.components[1] * o.components[1]
                + this.components[2] * o.components[2];
    }

    // Метод векторного произведения
    public Vector3f cross(Vector3f other) {
        float x = this.components[1] * other.components[2] - this.components[2] * other.components[1];
        float y = this.components[2] * other.components[0] - this.components[0] * other.components[2];
        float z = this.components[0] * other.components[1] - this.components[1] * other.components[0];
        return new Vector3f(x, y, z);
    }

    // Проверка типа вектора
    private boolean isVector3f(AbstractVector other) {
        return other instanceof Vector3f;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof Vector3f)) return false;
        Vector3f other = (Vector3f) obj;
        return Float.compare(components[0], other.components[0]) == 0 &&
                Float.compare(components[1], other.components[1]) == 0 &&
                Float.compare(components[2], other.components[2]) == 0;
    }

    @Override
    public int hashCode() {
        return Objects.hash(components[0], components[1], components[2]);
    }

    @Override
    public String toString() {
        return "Vector3f{" +
                "x=" + components[0] +
                ", y=" + components[1] +
                ", z=" + components[2] +
                '}';
    }

}
на его основе переделай мой класс для работы с векторами длинной 2package com.cgvsu.math;

import java.util.Objects;

// Это заготовка для собственной библиотеки для работы с линейной алгеброй
public class Vector2f extends AbstractVector {
    // методы для векторов - нормализация и расчет длины. Операции над ними будут описаны в другом классе
    private float x, y;
    private float lenght;

    // Конструкторы + getters and setters
    public Vector2f(float x, float y) {
        this.x = x;
        this.y = y;
    }

    public float getX() {
        return x;
    }

    public void setX(float x) {
        this.x = x;
    }

    public float getY() {
        return y;
    }

    public void setY(float y) {
        this.y = y;
    }

    // операции для векторов
    private void calcLength() {
        lenght = (float) Math.sqrt(x * x + y * y);
    }

    public float length() {
        calcLength();
        return lenght;
    }

    @Override
    public Vector2f add(AbstractVector other) {
        if (!isVector2f(other)) {
            throw new IllegalArgumentException("Invalid vector type for dot product");
        }
        Vector2f o = (Vector2f) other;
        return new Vector2f(this.x + o.x, this.y + o.y);
    }

    @Override
    public Vector2f subtract(AbstractVector other) {
        if (!isVector2f(other)) {
            throw new IllegalArgumentException("Invalid vector type for dot product");
        }
        Vector2f o = (Vector2f) other;
        return new Vector2f(this.x - o.x, this.y - o.y);
    }

    @Override
    public void multiply(float scalar) {
        this.x *= scalar;
        this.y *= scalar;
        calcLength();
    }

    @Override
    public void divide(float scalar) {
        if (scalar == 0) throw new ArithmeticException("Division by zero");
        this.x /= scalar;
        this.y /= scalar;
        calcLength();
    }


    // логика такая: если длина != 0 - просто делим, если = 0, то возвращаем текущий вектор
    private void calcNormalize() {
        calcLength();
        if (lenght == 0) {
            return;
        }
        divide(lenght);
    }

    @Override
    public void normalize() {
        calcNormalize();
    }

    //скалярное произведение
    @Override
    public float dot(AbstractVector other) {
        if (!isVector2f(other)) {
            throw new IllegalArgumentException("Invalid vector type for dot product");
        }
        Vector2f o = (Vector2f) other;
        return this.x * o.x + this.y * o.y;
    }

    private boolean isVector2f(AbstractVector other) {
        return other instanceof Vector2f;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof Vector2f)) return false;
        Vector2f other = (Vector2f) obj;
        return Float.compare(x, other.x) == 0 &&
                Float.compare(y, other.y) == 0;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y);
    }

    @Override
    public String toString() {
        return "Vector2f{" + "x=" + x + ", y=" + y + '}';
    }
}