I'm new to OOP and I'm trying to create two objects at the same time, with a HAS-A relationship. I have a Box object, which has a Contents object inside it, and I'm struggling with how a constructor should deal with that sensibly. My research has mostly dug up things about constructor chaining within a single class. The contents object also picks a ContentsType out of an enum:
Box:
public class Box {
double volume;
Contents contents;
public Box(int inputVolume, String inputContInfo, ContentsType inputContType){
this.volume = inputVolume;
contents = new Contents(inputContInfo, inputContType);
}
}
Contents:
class Contents {
ContentsType contType;
String contInfo;
Contents(String inputContInfo, ContentsType inputContType){
this.contInfo = inputContInfo;
this.contType = inputContType;
}
}
ContentsType:
public enum ContentsType {
CARGO,
GIFT,
OTHER;
}
The above Box constructor works, but is this breaking the encapsulation of the classes? It seems wrong, and I'd like to find what the accepted way to do this is. Any suggestions would be greatly appreciated!
edit:
I'm just trying to create a box from its constructor, eg:
Box aBox = new Box(2, "Something", ContentsType.CARGO);
No it is not breaking the encapsulation of classes. This can be an example of structural design pattern where you are changing the nature of a class without actually exposing the implementation of the class to the client.
Make sure you make your fields private - as you don't want anyone modifying the values directly. Other than that, your code looks fine.
I don't understand how is this code breaks encapsulation. As your research is on constructor chaining, this code is well and good. Otherwise I would have suggested to create Box and Contents separately and provide a Contents setter in Box class.
Related
Good morning, i'm learning java and i have a question.
I have a class "table" with a constructor, that accept a "fields", and put it in PRIVATE variable.
the question is: it is right to pass the object and use a "=" to put in the PRIVATE variable, or it's better to clone it?
if i use a "=", the variable inside my class are still editable from the method that used the constructor of the class, and eventually put NULL inside it.
for example:
class Table{
private Field field;
table (Field field)
{this.field=field;}
public String getValue()
{return field.toString(); }
}
main{
Field field=new Field("VALUE1");
Table table(field);
field.value="VALUE2";
System.out.println(table.field.getValue());
}
and the result is "VALUE2".
So in the table passed a value, and then i alter it.
but for the "good programming art", it is acceptable, or is better
class Table{
private Field field;
table (Field field)
{this.field=field.clone();}
public String getValue()
{return field.toString();}
}
main{
Field field=new Field("VALUE1");
Table table(field);
field.value="VALUE2";
System.out.println(table.field.getValue());
}
prints VALUE1
so if i pass a value to a Table, i can't modify it without using the Table methods?
what is the right way to to this?
This is a good question and points to a real problem. The recommended way to do this would be to have your classes immutable.
So the problem is not in the Table class, but in the Field class - it should only allow the modification of the value through the constructor, not through direct changes or with setters. Doing that you won't have this issue.
Declaring a variable private has nothing to do with its immutability. If the object passed to you is not immutable then I would suggest making a (deep) copy, otherwise you cannot rely on it not being changed elsewhere.
Other way would be making the Field class immutable, then you wouldn't have to make a copy, you would just save the reference in a private field.
There is no right or wrong way to do this in Java. Java passes objects by reference, and you need to understand that objects passed by reference are usually mutable, meaning they can change state. In Java, this is the expected behavior, but it can be confusing at first. It can also be very difficult to manage in a multi-threaded environment.
You do have the option, as #eis has indicated, to use immutable objects. There are many advantages to this, especially in multi-threaded code, but also some disadvantages. That discussion is too long and involved to get into here.
If you are concerned specifically with Java collections, the collections framework allows you to make a collection immutable. See the java.util.Collections.unmodifiable* methods for details on how to do that. Those methods can make an unmodifiable view of a collection without the overhead of cloning the data.
When you want the second object to see your original object over its lifetime, no matter how you change it, clone it before you pass it, or use an immutable object in the first place. When you want to ensure the second object cannot change your object, make it either immutable or use a read-only view as the Java collections do.
Good morning to you too.
I guess that you already know that Java is pass by reference value, so in the first case, table.field and field are "pointers" to the same object. Thus, modifying one will modify the other and viceversa. If that is what you want in this case then your first implementation would be correct.
On the other hand, if you just want to pass an object and you wouldn't be using the object field that you created, the following would be better suited:
Table table(new Field("Value 1"));
Lastly, if you just want to pass the value and you field and table.field referencing different objects that happen to have the same value. Modifying one won't modify the other. The clone() method is a valid solution, but not all classes implement this method. If the class Field didn't support the method clone(), your best bet is to implement a method similar to this in the Field class:
class Field {
//...Your code...
//First possibility
public void copyField(Field originalField) {
this.atribute1 = originalField.attribute1;
this.atribute2 = originalField.attribute2;
//This way you copy all the attributes manually
}
//Second possibility (a static method)
public static void copyField(Field newField, Field originalField) {
newField.atribute1 = originalField.attribute1;
newField.atribute2 = originalField.attribute2;
//This way you copy all the attributes manually
}
}
//**Using each method to make a copy of field1 in field2**
Field field1 = new Field(...);
Field field2 = new Field();
field2.copyField(field1); //Non-static method
Field.copyField(field1, field2); //Static method
Yet another solution would be to make a copy constructor which would be almost exactly the same as the non-static method:
public Field(Field fieldToCopy) {
this.atribute1 = fieldToCopy.attribute1;
this.atribute2 = fieldToCopy.attribute2;
//...
}
As you can see there are several correct ways to do this. You need to be able to chose and implement any of them depending on the particular problem you are solving.
Suppose you create an object:
class newClass{
public static void main(String[] args){
Object o = new Object();
}
}
Is it possible to return the name as a string, "o", or in anyform, of the given object?
No, this is not possible. If you really want this, you are probably using the wrong design. Note that objects do not have a name. Variables do have a name.
Is it possible to return the name of an Object in Java?
If you write something like this:
String name = obj.toString();
It will return string representation of object but this is not very human-readable. if you want to do it you need to create custom object and override toString() method:
public class MyObject {
private String name;
public String toString() {
return name;
}
}
Now when you write:
String name = myObj.toString();
It will return name in human-readable form. But this depends of your requirements if you want to create custom objects. In this way it's very simple and it works well.
No. The object does not know what the outside world calls it, i.e what reference(s) it has.
This is not possible.
You could use a Map<String, Object> to store a mapping from object name to object value and then return the key.
In reality the "name" of your object is a compile time constant. I.e. it doesn't change once you have compiled the code so
Object o = new Object();
return "o";
Would literally do what you want. Which begs the question, why would you want to do that?
This is not possible using java reflection. However, the information is stored in java class file if compiled with debugging information on. You may use bytecode engineering library like ASM to dig that.
Note: I just read sajmon's answer and he has the more elegant way of doing it to a certain extent
First of all the guys' answers are correct
but
if you really need it
I would extend Object class with something like MyObject
public class MyObject {
private String objectName;
public MyObject(){
}
public MyObject(String name){
setObjectName(name);
}
public getObjectName(){
return this.objectName;
}
public setObjectName(String name){
this.objectName = name;
}
}
but then each time you create an Object use MyObject instance instead and add your object name as a constructor parameter
MyObject mine = new MyObject("mine");
Having said that, it's still an open question as to why you might need it? :)
Since Java supports aliasing this really isn't sensible or possible.
Aliasing means there's no garuantee that an object is referenced by only one variable.
scoping just makes the whole problem even harder, since only references in the current scope would be of any use at that point. and there may be more than one.
it would help if you explained what you're trying to achieve with this code.
In addition to the previous answers, there may be several different variables, with different identifiers, that all reference the same object. A variable may refer to different objects at different times.
If you need a mapping from an object to a String, I suggest a Map<Object,String>.
Say I have some class:
public class A {
private int val = 0;
public int getVal() {
return val;
}
public void addFrom(A otherA) {
this.val += otherA.val;
if (otherA.val > 0)
otherA.val = 0;
else
otherA = Math.abs(otherA.val);
}
}
Should I be using getter methods instead to use otherA's val variable? Is it better style to do so?
Edit: This is a very simplified version of a class that takes much too long to read. But assume that there IS lazy initialization going on, that there are other methods that access this class, etc. I have updated the example method so that this may be more clear, but I hope it is clear that my question involves accessing the other object's variables, and want to know if it is faux pas to use a direct variable access for something that is not "this".
No, absolutely not.
You should use the variable directly when you're inside the class' members, and use getters in every other situation (when you would get an error because val is private anyway).
public int getVal() is intended to present your gift(variable) within a box to the outside world (encapsulation). Do you give gifts yourself in a box? It's weird, so use the variable as it is.
You can use variables, but the current code does not compile. Probably, the return should be int instead of boolean.
Probably, your intention is to override the compareTo method from the Comparable interface
Adding an unnecessary getter reveals internal structure and this is an opportunity for increased coupling.
A truly well-encapsulated class has no setters and preferably no getters either. Rather than asking a class for some data and then compute something with it, the class should be responsible to compute something with its data and then return the result.
Use of accessors to restrict direct access to field variable is preferred over the use of public fields, however, making getters and setter for each and every field is overkill. It also depends on the situation though, sometimes you just want a dumb data object. Accessors should be added for field where they're really required. A class should expose larger behavior which happens to use its state, rather than a repository of state to be manipulated by other classes.
Despite Java tutorials, Wikipedia searches, stackoverflow trolling, and hours of reading code samples, constructors still confuse the crap out of me. I've got three related questions that I've been trying to answer to help ME understand constructors a little better.
First, I've been under the impression that constructors need to be named the same as their classes. Consider:
public class Money {
public Money(long l) {
this.value = l;
}
public Money(String s) {
this.value = toLong(s);
}
public long getLong() {
return this.value;
}
public String getString() {
return toString(this.value);
}
}
I see this as four constructors...correct? So it appears that constructors not named the same as the class which contains them allowable. Can someone confirm that?
Second, I seem to have a block against understanding the set and get methods. Consider:
public class GetSetSample {
public int getFoo() {
return int Foo;
}
public void setFoo(int fooValue) {
int Foo = fooValue;
}
}
Why can't I just do this:
public class getFoo(int fooValue){
foo=fooValue;
}
and use foo = getFoo(12) from some other class/method?
The third question is a little more esoteric, but will help me conceive of the bigger picture...which is my learning style, and conducive to my ability to trace program flow when debugging. The get and set methods suggest a "to" and "from" relationship to me. e.g., Passing a value "to" a constructor, receiving the result "from" the get method. It seems to me though that the "to" and "from" will change depending on your perspective. I think that any setMethod is setting parameters for an object, even though the variable comes FROM another class or method, and the GetMethod is getting the resulting object (say, this.foo) with the appropriately set parameter. No matter where the get or set is used, in a main method or a standalone class with a single constructor, 'set' is always associated with sending a parameter and get is always associated with receiving an object with that parameter. Is that a good understanding? or am I missing a vital part?
Question 1:
I see this as four constructors...correct?
No, that class has two constructors and two methods. (getLong and getString are the methods.)
Question 2:
Why can't I just do this:
public class getFoo(int fooValue){
foo=fooValue;
}
Well, that's trying to declare a class with parameters, and also you're setting a value in a get method, which would be extremely weird. It's not clear what you're trying to achieve here, but that code is thoroughly invalid.
Question 3:
The get and set methods suggest a "to" and "from" relationship to me.
Well it's not really a relationship IMO. A relationship suggests something longer term than either of these methods. A setter typically changes the state of an object in some way, and a getter typically just returns some aspect of the state of an object. It's not really clear what the rest of your explanation meant, because you're playing somewhat fast and loose with terminology. For example: "get is always associated with receiving an object with that parameter" doesn't really make sense to me. Objects don't have parameters, methods/constructors do - and getters can fetch primitive values or references...
I suspect you would benefit from reading the "Classes" part of the Java tutorial, which talks about constructors and methods.
Regarding the first answer, there's only 2 constructors. The difference is on how they are going to be called (called using a string will use the construction having a string has a parameter and called using a long will use the other one). So to answer, yes a constructor has the same name as the class.
The two constructors :
public Money(long l) {
this.value = l;
}
public Money(String s) {
this.value = toLong(s);
}
Regarding the second answer, getters ans setters are not meant to be classes. They are supposed to be within the class itself.
Consider this example which uses getter and setters to get ans set value for the printer class :
public class Printer {
#Inject #Informal Greeting greeting;
private String name;
private String salutation;
public void createSalutation() {
this.salutation = greeting.greet(name);
}
public String getSalutation() {
return salutation;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
A good read of this link could definitly help you out !
Java oriented-object principles
You've shown 2 constructors, which do need to have the same name as the class.
You've also shown two "getter" methods, which return the value of the class variable in the form requested by the user. You can also create "setter" methods, which are used to transfer values into class variables.
You use a constructor to create an object of a particular class, and optionally to set some or all of its internal state (that is, its member variables).
You use setters and getters to isolate the class variables from the outside world, so you don't need to allow other code to access them directly. Why? Because, before a setter updates a variable, it can verify that the new value is valid, and that the operation doesn't violate any or the rules (the "business logic") that are required for the class to work properly.
So you could add a setter and update the constructor to use it:
public Money(long l) {
setValue(l);
}
public Money(String s) {
setValue(toLong(s));
}
// Example setter that validates `l` by prohibiting negative values
public Money setValue(long l) {
if (l < 0) {
// Warn about negative values
}
this.value = l;
return this; // Return the current object to allow chaining; see below.
}
Note that a setter usually doesn't need to return a value (that is, it can be type void), but it's often helpful to return the object itself. That allows you to write code like this:
Money earnings = new Money().setValue(4).setOtherField("foo");
This creates an object of type Money, sets various attributes, and stores it in the variable earnings. Clearly, this isn't terribly useful for a simple class like this, but it can be very helpful for more complex classes:
Paycheck check = new Paycheck("MyCompany")
.setEmployee("YourName")
.setSalary(50,000)
.setPaySchedule(Schedule.BIWEEKLY)
.setAccountNumber("1234567")
.setDefaultTaxRate();
I would like to try to answer your implied conceptual questions -- you've already got plenty of examples of this and that, so I'm just going to try to explain. I have no doubt you have heard most of this -- maybe all of this -- before, but am not sure and not sure which parts.
Object-oriented programming centers mostly around objects; an object is an amalgamation of code and data. You define objects by writing a class, and you create one or more copies of the object defined by that class with the class constructor (called instantiating the class).
A parallel in other languages: you can have a data structure of related items and a set of subroutines that operate on that data structure. Think of a class as a way of collecting the items in that data structure and the subroutines that operate on it into one unit.
After you have invoked a constructor, you have a copy of the data defined in that class and a way to refer to that copy. By referring to that instance when you invoke a class method, you operate on that copy of the data with the methods defined in that class.
If you were to do this in a non-OO language, you could have a routine that created a copy of the data structure in memory and then only use the methods prescribed for it on that data structure. You could have a pointer to the copy in memory and pass that pointer as a parameter to every subroutine that operated on it, and in fact that's the way some pre-OO systems were programmed.
A constructor is similar to a method call that returns a value; it involves (or can involve) the execution of statements, and it always returns an object of that class. There are also differences between a constructor and a method; until the constructor completes, for instance, the object is not fully created and shouldn't have some methods invoked on it.
So I hope that helped; if there are conceptual things you still have questions about, perhaps something in here will help you form a specific question so we can explain things further.
Many people have found that if they have spent years learning languages such as COBOL and FORTRAN then changing to OO programming involves unlearning the old languages. I certainly found this when I first tackled C++ 20 years ago. From your description you are clearly struggling with the concepts and I sympathize.
I don't think there is a simple recipe. Practice at the simple examples and don't be disheartened. Don't be afraid to ask on SO - if the questions are clearly asked you will get a useful answer.
Get a good IDE (Eclipse, Netbeans, etc.) which allows you to "look inside" objects with the debugger. Hopefully at some stage things will click!
Question 1 - Basic Java Classes:
There's pretty much only 3 things you're going to find in a Java class
Field/attribute (Depending on your language of origin)
Method
Constructor (Which looks like a special kind of method)
Every class is going to have a class name that shares the name of the file it's located in. So to expand Money out a bit:
Money.java
----------
public class Money {
// This is a field/attribute
Long value;
// This is a constructor
public Money() {
this.value = Long(0L);
}
// This is a method
public Long getValue() {
return value;
}
// Another method
public void makeMoney(Long moreMoney) {
this.value = this.value + moreMoney;
}
} // Everything in here is part of the Money class
The only distinction between a constructor and a method is that a constructor has no specified return value, which is declared as a type right before the name of a potential method. Constructors do have to be named the same as the class they are contained in, but why is implied in how they are written.
Another way of looking at it is if you remove all of the non-type related Java keywords (public, private etc., but not things like float and int) from the front of the method you're looking at (A list of which you can find here), is there anything left in front of the method?
With the Money we have at the moment, it would look like this:
Money()
Long getValue()
void makeMoney()
The constructor is the one that has no type for the return value, because it is implied in the declaration.
Question 2/3 - Get/Set methods:
I'm going to say something potentially controversial, but don't worry about these yet. Get/Set are essentially patterns for Object Oriented development, and generally good Java style, but they aren't required (Last I checked, Android development actually discourages their use when possible for optimization reasons). Moreover, not all fields in your objects will be accessible or mutable so writing them isn't mandatory.
If you declare all of your fields as public (Like the 'value' field is implied to be right now), you simple can do this:
Money myMoney = new Money(new Long(40L));
System.out.println(myMoney.value) // 40
myMoney.value = new Long(20L);
System.out.println(myMoney.value) // 20
Aside from that, the notion of get() and set() are just methods. There is nothing special about them at all. The main reason they exist is because for general Object-Oriented programming, you shouldn't have to directly modify the internal workings of an object (This is the principle of Encapsulation). Everything you should need to affect state or get something out of it should be handled by a method.
In a pithy one-liner: If you need to know the fields of an object to use it, you designed it incorrectly.
Big Picture
So what get() and set() really are is a pair of commonly written methods that happen to affect a field in an object in an extremely simple way (get() is a simple access to a field, set() is assignment to that field). It's just that other methods you write will happen to do more complicated stuff than that.
So I'm learning java. I'm one month in and I just learned about constructors. But I don't see the whole purpose of creating one. Why and when would I ever want to use one? I get the whole idea that it does not have a main method and you can call a constructor from your main class. Anyone can enlighten me on this topic, it would help me a great deal.
Constructors are what you use to initialize/set up the instances of your classes.
If you have an object that needs some processing before it is usable (initializing members for instance), you should do that in the constructor.
Ideally, you should never have "partially built" objects (i.e. objects that are "live", that you hold a reference to, but that are not yet usable). Without constructors, you'd be permanently creating partially built objects, and that is very error-prone. (Theory and practice don't always match, but keep that idea in mind.)
You use a constructor to create new objects. Yes, you can write Java just using static methods - but then you're really not writing object-oriented code, and you'll have a hard time using much of the standard library, either.
Most of your time you should be working with and thinking in terms of objects - and they need to be constructed before they can be used... and that's where constructors come in. They create an object, often with parameters specifying the initial state or other important information about the object.
To be honest, it's probably not worth worrying about them just yet, if you don't see the point yet. It's likely that as you learn more, you'll naturally start using objects more (maybe collections to start with, for example) and you'll get the hang of it. Rest assured, it is important to have constructors in Java, but I'm sure you'll understand why in the course of time. (Of course, if this answer has helped you to appreciate their value already, I'm glad - but if not, don't worry :)
It might seem as if you're having trouble understanding the basic concepts of objects and object-oriented programming. An explanation by example; This class represents a type of thing, namely a car:
public class Car{
// Licence plate number. This is private, so it can
// not be accessed directly from outside the class.
private String hiddenRegNr = "";
private static String description = "This is a car".
// The constructor, which sets the value of hiddenRegNr
public Car(String regNr){
hiddenRegNr = regNr;
}
// Method for reading hiddenRegNr, the only
// way to access it after instantiation.
public String getRegNr(){
return hiddenRegNr;
}
// A static method. Can be used withouth instantiation.
public static String getDesc(){
return description;
}
}
From some other class, you could call this class, and make instances of it; actual representations of different cars. They represent different cars, but are based on the same "model", i.e., the class Car.
Car myFirstCar = new Car("SR12345");
Car myOtherCar = new Car("XZ54321");
Now you have two different cars, with two different registration numbers. These are independent instances of the type car. They exist in memory, and may contain different values (in this case, different registration numbers).
myFirstCar.getRegNr(); // Will return SR12345
mySecondCar.getRegNr(); // will return xz54321
The first thing to notice here, is that you can only specify the registration number once per car, namely upon creation. That is the point of the constructor: It sets values, and does other stuff that needs to be done when objects (instances) are created.
Now, note the difference between getRegNr() and getDesc(): The keyword "Static" means that the second method is related directly to the class, and not to each instance. This means that:
Calls to getDesc() is made on the class, not an instance:
Car.getDesc();
Calls to getDesc() will return the same value for all instances of the class car
The variable description (which is also static) will be the same for all instances of Car
The static method getDesc() CAN NOT access the variable hiddenRegNr, since that variable is related to a specific instance. Trying to refer to a variable in an instance from a static context (such as getDesc()) will cause an exception to be thrown. You might say that hiddenRegNr will not have been set when you call
Car.getDesc();
because the constructor was never called, so it was never given any value.
Constructors are used to initialize a class and give parameters to a class. What is important is that they let you set the class state on creation. This allows you to use specific instances of a class with different data field values instead of relying on purely static information. Take the following example:
class Obj {
private int state = 0;
public Obj(int state) {
this.state = state;
}
public Obj() {
state = 1;
}
}
Now in main (or wherever) you can have:
Obj obj1 = new Obj();
Obj obj2 = new Obj(2);
The two objects have different states (one is at state 1, the other is at state 2). If you were relying on static methods and members, the objects would share one state and would not be independent of each other.
It is also important to note that constructors (specifically the new keyword) allocate memory for a given object internally so you don't have to worry about using malloc and other memory management. So they are important in that sense as well.
It is used to create objects. Objects are the main concept in OOP, so creating them is an important step. The main class method is just an entry point to your program. If you don't create objects your program will be procedural rather than object-oriented. This is why to use a constructor.
And why to create a constructor - sometimes you need to construct an object with some required parameters. There is also a default no-argument constructor, but if you want to initialize your object with additional arguments - you create a constructor taking those arguments.
Actually constructor is needed IF you need to assign unique initial state to an instance of a class. In Java i only just realized (by a friend) that we can do this:
public class MyClass1 {
private class MyClass2 {}
private MyClass2 myobj2 = new MyClass2();
}
So no need for implicit constructor.
But if something like follows, you need constructor.
public class MyClass1 {
private class MyClass2 {
private int id_ = 0;
public MyClass2(int id) { id_ = id; } // how to reach this?
}
private MyClass2 myobj2 = new MyClass2(1); // (this doesn't work. Not unique)
public MyClass1(int id) { myobj2 = new MyClass2(id); } // by this!
}
MyClass1 obj1 = new MyClass1(100);
MyClass1 obj2 = new MyClass1(200);
I will give you an example, imagine you have a car class.. when you call the constructor of the car class you have an car object. on this car object is possible to use diffent methods. And you could create as many as car objects as you want.