Геттеры и сеттеры для массивов - PullRequest
11 голосов
/ 12 июля 2011

У меня есть несколько вопросов о геттерах и сеттерах для массивов. Предположим, у нас есть такой класс, который создает частную копию массива в своем конструкторе:

import java.util.Arrays;

public class Foo
{
    private int[] array;

    public Foo(int[] array) {
        this.array = Arrays.copyOf(array, array.length);
    }
}

Мы хотим, чтобы массив мог быть доступен / изменен только через геттеры и сеттеры. Если у нас есть геттер, который выглядит так:

public int[] getArray() {
    return array;
}

он побеждает цель получения, так как мы возвращаем ссылку, которая позволяет пользователю напрямую изменять элементы массива. например,

Foo foo = new Foo(someArray);
...
int[] bar = foo.getArray();
bar[0] = 123; // Now foo.array[0] = 123 and we haven't used a setter!

Итак, предположительно, нам нужно что-то вроде этого:

public int getElement(int index) {
    return array[index];
}

Аналогично для сеттеров. Но если мы делаем что-то отдельно для каждого элемента, нам также потребуется предоставить способ получения длины:

public int getArrayLength() {
    return array.length;
}

Это уже немного грязно для одномерного массива, но скажем, у нас вместо этого многомерный массив:

import java.util.Arrays;

public class Foo
{
    private int[][][] array;

    public Foo(int[][][] array) {
        // Code for making a deep copy here
    }

    public int getElement(int i, int j, int k) {
        return array[i][j][k];
    }

    public void setElement(int i, int j, int k, int value) {
        array[i][j][k] = value;
    }

    public int getArrayLength() {
        return array.length;
    }

    public int getArrayLength(int i) {
        return array[i].length;
    }

    public int getArrayLength(int i, int j) {
        return array[i][j].length;
    }
}

Это много кода для такой тривиальной задачи, и что более важно, это беспорядок, который нужно использовать. Нужно ли нам в конечном итоге что-то подобное или есть лучший способ сделать это? Я посмотрел повсюду, и, похоже, для этого нет «стандартной практики».

Ответы [ 4 ]

8 голосов
/ 12 июля 2011

Многомерный массив также является одномерным массивом: int[a][b][c] на самом деле просто int[a*b*c], поэтому проблема сводится к тому, как обеспечить безопасный доступ?Просто так:

public class Foo {
    private int[] array;

    public Foo(int[] array) {
        this.array = Arrays.copyOf(array, array.length);
    }

    /** @return a copy of the array */
    public int[] getArray() {
        return Arrays.copyOf(array, array.length);
    }
}

Вот и все.

Вызывающие имеют безопасную копию массива и могут использовать ее полностью обычным способом, как используются массивы.Нет необходимости в методах делегатора.

1 голос
/ 12 июля 2011

По отношению к первой части ваш геттер может не выглядеть как конструктор?

public int[] getArray() {
    return Arrays.copyOf(array, array.length);
}
1 голос
/ 12 июля 2011

Что, по вашему мнению, ArrayList делает или Vector до этого?

Я думаю, что лучший вопрос заключается в том, почему в этот момент вы выставляете, что Foo вообще поддерживается массивом? Если вы пытаетесь инкапсулировать его, вам не нужно иметь аксессоры и сеттеры повсюду. Если вы просто пытаетесь создать оболочку класса вокруг массива, я бы предложил вам иметь интерфейс, назвать его IntList или что-то в этом роде и сделать Foo конкретной реализацией, опирающейся на список.

0 голосов
/ 13 июля 2011

Я написал небольшой API для многомерных универсальных массивов. Там у вас есть геттеры, сеттеры для каждого элемента, какими бы ни были ваши размеры.

MDDAJ на github

Вот пример: создание массива 5-мерных строк:

MDDAPseudo<String> c = new MDDAPseudo<String>(10,20,5,8,15);
c.set("xyz", 0,0,2,1,0); // setter indices: [0][0][2][1][0]
String s = c.get(0,0,0,0,0); // getter indices [0][0][0][0][0]

Богемский уже писал, что вы можете использовать только одно измерение. В этом случае класс PDDAPSeudo internal также имеет одно измерение. Но API предоставляет вам доступ как многомерный массив

...