tags:

views:

244

answers:

3

Hello, I am not sure about some things in OOP.

If I have Class1, which has some private field, for example private Field field1, and make

getField1 () {
    return field1;
}

then I have some class with constructor

public Class2 (Field field) { 
    someMethod(field);
}

And then I call constructor of Class2 in Class3 like:

Class2 cl = new Class2(instanceOfClass1.getField1());

And now the question: Am I working with field1 of instanceOfClass1 in someMethod(field)?

+1  A: 

You're working with the value contained in it. If it is a mutable object then yes, it is possible to change the state of the instance of Class1 from outside, which violates data protection principles. This is why you should copy mutable types before returning them.

Ignacio Vazquez-Abrams
but what If I need to track exactly that instance, and someMethod(field) put the field to some global lookup? How to solve it with copying?
venom
If you make a deep copy of a mutable object then any mutations to the object won't affect the copy.
Ignacio Vazquez-Abrams
+4  A: 

This depends on whether field is a value or a reference.

Value types are copied when passed as parameters. Reference types are not; the function is simply handed a "reference" that points back to the original value, and any changes that it makes are reflected in the original value.

Whether a given type is value or reference depends on your particular programming language. Generally speaking, basic integer and boolean types are usually value types, and everything else is up in the air -- some languages make strings values, and others treat them as references, etc.

Edit: Since you mentioned you're using Java, here's a short program that demonstrates value and reference types:

class ClassOne {
    public int myInt;
}

class ClassTwo {
    public int myInt;
    public ClassTwo(ClassOne c)
    {
        myInt = c.myInt;
        c.myInt = 3;
    }
}

public class main
{
    public static void main(String[] args)
    {
        ClassOne c = new ClassOne();
        c.myInt = 1;
        System.out.println("C1: " + c.myInt);

        ClassTwo c2 = new ClassTwo(c);
        System.out.println("C2: " + c2.myInt);
        System.out.println("C1: " + c.myInt);

    }
}

Running this program will give the output:

C1: 1
C2: 1
C1: 3

In this program, both ClassOne and ClassTwo contain an integer field -- a value type. ClassTwo takes a ClassOne parameter -- a reference type -- in its constructor, and sets its own integer field based on the value of the ClassOne object it is given, and then changes the ClassOne object's value.

Because classes are reference types, changing the ClassOne object in the ClassTwo constructor causes the original object to be changed. (In the main function here, that's c.) But because integers are value types, even though c2 changes the value of c.myInt in its constructor, because it sets its own value beforehand, c2.myInt isn't affected: it retains the original number, because it was copied rather than referenced.

Hopefully this helps clear things up a bit.

Dan Story
When I create ArrayList<MyClass>, and private MyClass cl; in java, are both reference?
venom
Class types in Java are always reference types. If you have a field in an object that is of a class type, and you pass that field value to another method, when it modifies the value you gave it, it is modifying the same class object your original field points to. Some classes are designed to be natively immutable to prevent confusion of this kind -- String is the most obvious example. Strings, once created, are not changed -- any operation which could change them (such as toUpperCase or substring) returns a new String instance instead.
Dan Story
A: 

I had to reread your question two or three times to make sure I understood what you're asking.

To recap:

  • There is Class1 which contains an field attribute (of type Field?) which is sent back by it's getField1() method.
  • There is then Class2 which is apparently has a constructor that accepts an object parameter of Field type and contains a method that uses an instance of Field to trigger a local method in this class.
  • You then use a third class to instantiate Class2 and initialize it using an instance of Field using the getField1() method from an instance of Class1.

In the case of Java, providing you've done the necessary instantiation this would mean that the Field instance in Class1 is being used throughout the process. You can verify this using a System.out.println() (this will give you an @ symbol with a series of weird numbers) or using the a.equals(b) method common to all objects.

Here is an interesting link about passing objects by value: http://www.javaranch.com/campfire/StoryPassBy.jsp

James P.