2013-04-19 2 views
4

Могу ли я сделать объект неизменным при передаче в качестве параметра , чтобы вызываемый метод не мог его изменить, но вызываемый может?Создание объекта неизменяемым при его передаче в качестве параметра

Так что я Somthing так:

Class Car { 
    Wheel wheel_1; 

    Axis axis = new Axis(wheel_1); 
} 


Class Wheel { 
    int size; 

    setSize(int size) {} 
    int getSize() {}  
} 

Теперь я построить машину с колесом. Затем из класса автомобиля я хочу построить ось.

Для этого я передаю wheel_1 в конструктор оси.

Теперь мой вопрос: могу ли я как-то позаботиться о том, что конструктор Axis не меняет размер wheel_1, но классный автомобиль может его изменить.

ответ

4

Да. Обычно это делается путем использования copy-constructor для класса Wheel.

Например:

wheel_1 = new Wheel(wheel); 

Имейте в виду, Wheel класс должны быть написаны таким образом, что поддерживает это. То есть, он должен либо предлагать экземпляр-конструктор.

Примечание: это не сделало объект неизменным. Он просто создал копию, которая не может быть отредактирована ничем, кроме вашего класса.

Если вернуть экземпляр Wheel любой из ваших других методов, убедитесь, защищаясь скопировать его на выход тоже:

Wheel getWheel() { 
    return new Wheel(wheel_1); 
} 

Наконец, стоит отметить, что это всегда хорошая идея создавать неизменные классы всякий раз, когда можете. Так что, возможно, вы можете избежать этой проблемы, фактически делая Wheel неизменяемым?

+0

Спасибо за ваш ответ :). Я тоже подумал об этом. Просто хотел знать, есть ли способ или «ключевое слово», например. окончательный (его не окончательный), который может быть использован. – eclipse

+1

В C# ICloneable не рекомендуется, так как вызывающий не может отличить, является ли клон глубокой или мелкой копией. Является ли Cloneable одинаковым в java и поэтому не следует использовать? – chrisw

+1

@ chrisw69 Да, 'clone()' обычно не нравится также сообществу Java, см. [Здесь, например] (http://jcranky.com/2009/08/26/why-not-use-java- клон-метод /). Я отредактировал сообщение, чтобы удалить упоминание об этом - возможно, не стоит его поощрять. –

3

Пропустить Axis конструктор копию wheel_1.

class Car { 
    Wheel wheel_1; 

    Axis axis = new Axis(new Wheel(wheel_1)); 
} 

Кроме того, Wheel потребуется конструктор, который принимает другой Wheel объект и копирует его свойства.

2

Почему вы не отправить параметр в качестве своего суперкласса, который не имеет SetSize() метод

Class Car { 
    Superwheel wheel_1; 

    Axis axis = new Axis(wheel_1); 
} 

class Superwheel 
{ 
    int size; 
int getSize() {}  
} 

Class Wheel extends Superwheel{ 
    int size; 

    setSize(int size) {} 
    int getSize() {}  
} 
+0

Все еще можно отличить Superwheel to Wheel и изменить размер. –

+0

Хм Мне нравится этот подход! потому что все равно останется только один объект. Но Субир прав, он все еще может изменить. В моем usecase это хорошее решение, потому что я просто не хотел добавлять колесо = новое колесо (колесо) каждый раз. – eclipse

+0

Похоже, что есть дублирование с суперклассом, почему бы не использовать интерфейс? – chrisw

1

Да, вы можете. Если вы сделаете автомобиль и колесо в том же пакете и объявите поля колесика, которые необходимо защитить. Таким образом, Axis, если он объявлен в другом пакете, не может получить доступ к сеттерам Wheel, что делает колесо неизменным с точки зрения Axis.

Ну, это решение является основным для начала. Конечно, вы можете думать о том, нужно ли сделать Колесо окончательное или нет, клонирование, сериализуемое и т. Д., Исходя из того, на каком уровне вы хотите сделать неизменным.

+0

Ну, на мой взгляд, это не очень хороший подход. Изменение структуры пакета только для достижения этой цели. Но рабочий ответ. Спасибо! – eclipse

+0

@eclipse Спасибо, это зависит от требования. Если вы работаете над простой программой, вы можете не захотеть сделать ее сложной. Как я уже сказал, это базовый подход и зависит от того, как далеко вы продвинетесь, вы можете использовать другие подходящие методы. – IndoKnight

2

У меня было бы колесо реализовать интерфейс, который имеет только методы доступа, i.е: -

Пример

interface WheelInterface 
{ 
    int getSize(); 
} 

class Wheel implements WheelInterface 
{ 
    // methods 
} 

class Axis 
{ 
    public Axis(WheelInterface wheel) 
    { 
    // Only getSize will be available 
    } 
} 

Теперь, просто передать WheelInterface вместо колеса и только методы доступа будут доступны конструктором класса оси

Преимущество

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

Пройдя эту же ссылку на объект по значению, вам не нужно называть какой-либо конструктор копий и не нужно беспокоиться о семантике глубокого и мелкого копирования. Я бы не хотел использовать Clone на моем колесе, я думаю, что это немного грязно по причинам, упомянутым в комментариях к другим ответам.

В объектно-ориентированном шаблоне использование интерфейса для абстрагирования от того, что вам не нужно, также является признаком хорошего дизайна. Если ваше колесо имеет зимние шины, ваш класс Axis, вероятно, даже не нужно заботиться!

Недостатками

Как уже упоминалось, можно отливать интерфейс обратно к конкретному типу (как уже упоминалось, если вы знаете, что вы литья в); это называется downcasting, и я не рекомендую его; если бы это было сделано по аналогичному сценарию, вероятно, он не прошел бы мимо обзора .

5

Сделайте класс Wheel неизменным. Затем пусть объект Car создает новый объект Wheel, когда ему нужен новый размер.

public final class Wheel { 
    private final int size; 

    public Wheel(int size) { 
     this.size = size; 
    } 

    public int getSize() { 
     return size; 
    } 
} 

Теперь вы можете без проблем передать колесный объект на ось.

public class Car { 
    private Wheel wheel; 
    private Axis axis; 

    public Car(int initialWheelSize) { 
     wheel = new Wheel(initialWheelSize); 
     axis = new Axis(wheel); 
    } 
} 
+0

Также хороший ответ просто не практичен для меня;). благодаря – eclipse

Смежные вопросы