What is the possible benefit (if any) of allowing recursive constructors? - java

In Java, constructors cannot be recursive. Compile time error: "recursive constructor invocation". Let's assume that we did not have this restriction.
Things to keep in mind:
The return type of a constructor is void. Since it is a void method you can't harness the complete power of recursion.
A constructor can invoke itself (or any other constructor) using this(). But a "call to this must be first statement in constructor"
We could use non local data between consecutive calls to still have some possible gain from recursive constructors.
Would there be any benefit from allowing recursive constructors?

Constructors (when they are calling each other) are like methods that return void. Consequently the only way they can produce results is by side-effects. This is then limited to mutating the object they are constructing or by mutating the values passed in as parameters. The latter is a pretty nasty idea in a constructor; a constructor usually takes information from its parameters without mutating them.
So mutating the object being constructed is the only option in order to have any way to track the progress of the recursion, in order for it to terminate eventually. And it's very hard to see how that would be easier to write, clearer to read, etc. than a simple loop inside an ordinary constructor.
Calling another constructor (with this) from within a constructor is of course totally different from using a new expression within a constructor:
class Node
{
Node _left, _right;
public Node(Node left, Node right)
{
_left = left != null ? new Node(left._left, left._right) : null;
_right = right != null ? new Node(right._left, right._right) : null;
}
}
Here the Node constructor calls itself, but via a new expression. This is the crucial difference. A new expression produces a value, so this is purely "functional", non-mutating stuff, and provides a convenient way to make a deep copy of the tree of nodes.

Constructors can be recursive. (That's in C#, but you can do the same thing in Java)

Let's look at this problem. First of all, what happens when you invoke new MyClass("foo");? Well there are two things happening. First of all, the virtual machine will allocate the memory needed to store an object of type MyClass. Then, the constructor gets called. The job of a constructor is to initialise this just allocated memory. Therefore, a constructor does not have a return type at all (not even void). The value returned by the new operator is a reference to the allocated memory, so the constructor can not return as well.
Then, what would be the benefit of recursive constructor invocation. The only benefit of such invocation would be to handle certain constructor parameters like others, and doing so by re-invoking the constructor. While this is possible it is generally easy just to adjust the values in the constructor itself (using non-final parameters), and after that initialise the object attributes (in short you don't need recursion for this).
Second, you can do recursion fairly easily by offloading all the work to a worker method that can recurse as much as you want.
A more interesting question is the restriction on super or this invocation being the first statement of the constructor. This restriction was probably put in to discourage sloppy or unsafe programming practices. Statement is put in bold here though as it is possible (although not beautiful) to work around this restriction. If you remember that expressions may have side effects (e.g. variable assignments), and expressions used for parameters are invoked before the call itself it is possible to create complicated expressions that do all your calculations before invoking the delegate constructor.
The general reason why you want to have a delegate/super constructor invocation later in the constructor body is parameter manipulation. You can do that with (static) helper functions that do these calculations and provide the correct values. This is generally cleaner but not in all cases. The actual execution speed should not be affected as hotspot can inline these things very well.
That means that in the end the consideration boils down to providing the flexibility of free placement of delegate/super calls versus the added safety provided by making incorrect practices quite much harder. The choice made by Java's designers (and the general Java philosophy) is to go for making it harder to do the wrong things at the cost of raw language power at the hand of experts (with increased complexity). The choice made is to me a valid one albeit I personally would like the power (one can always implement a java++ language on the JVM that does not have these restrictions).

You might not be able to write a recursive constructor, but you can call a recursive function from your constructor. I have never had to do this before, and I can't think of a situation where you might need to, but you can do it if you want.

What do you mean allow? You can have recursive constructors in Java. They allow you to reuse code and design your constructors in a more hierarchical fashion.
In the following recursive constructor example, I can call new User() or new User("Marcus") and with either constructor that I use, newUser is set to true.
public class User() {
public String userName;
public boolean newUser;
User() {
newUser = true;
}
User(String userName) {
// Recursively call no-argument constructor
this();
this.userName = userName;
}
}
Here's the same thing without recursive constructors. Notice the duplicate line of code:
public class User() {
public String userName;
public boolean newUser;
User() {
newUser = true;
}
User(String userName) {
newUser = true;
this.userName = userName;
}
}
In the following non-recursive constructor example, if I don't pass a name into the constructor, then the name is set to "New User". I would only want to call the no-argument constructor if I'm not setting the name. If I did a recursive constructor call here, I would end up setting the userName twice:
public class User() {
public String userName;
User() {
this.userName = "New User";
}
User(String userName) {
this.userName = userName;
}
}
You will only use recursive constructors if you:
Have more than one constructor
Have code in your constructors
Want to recursively use code that's in another constructor

The return type of a constructor is
void.
No it isn't.
A constructor can invoke itself (or any other constructor) using this()
No. It can only invoke other constructors, and only if that won't lead to a recursive invocation of the current constructor. That's why you get the error message you referred to.
We could use non local data between
consecutive calls to still have some
possible gain from recursive
constructors.
How? Why would you want to re-initialize an object? When can't you do it sequentially in one pass? Never had this problem in 39 years of computer programming, and 20 years of OO.
Would there be any benefit from
allowing recursive constructors?
You haven't come up with any ...

Related

What is the difference between void method and return this

Class Player {
Player setName(String name){
this.name = name;
return this;
// or
void setName(String name){
this.name = name;
}}
Hi. What is the difference if I use the method with "void" or "return this" statement? Why the "return this" statement exists, if it does the same?
Why the "return this" statement exists, if it does the same?
They don't remotely do the same thing.
A void method has no return value. That means you can't use the return value (for instance, you can't assign it to a variable).
A method with a return value has a return value. In the particular case you've mentioned, return this, it's returning a reference to the object that the method was called on, so you can (potentially) use that reference — by assigning it to a variable, by calling another method on it, etc. This is useful for fluent interfaces (ones that allow you to do a lot of chaining):
theObject.doThis().thenDoThat().thenDoSomethingElse();
If it were void instead, you'd have to write that like this:
theObject.doThis();
theObject.thenDoThat();
theObject.thenDoSomethingElse();
Probably the most famous example of this1 is Builder pattern of object construction, because it means you don't need a variable:
Thingy t = new ThingyBuilder()
.withFoo("foo")
.withBar("bar")
.withBaz("baz")
.build();
1 Most famous outside web development circles, that is; inside web development circles, the most famous example would be jQuery's API: $("div").css("color", "green").text("Good");
The first is used for chaining methods (builder pattern) while the second is a plain vanilla setter method
When you return this, you return a Player instance.
More commonly used in the Builder Pattern, this returns a Player with the name of Joe.
Player p = new Player().setName("Bob").setName("Joe");
Using the void method, you cannot do the second setName. In order to rename the player, you'd have to get the first instance of the player object, then call setName again on the following line.
Obviously, a simple example, but is more useful when you have lots of setters like so
new Player()
.setName("Bob")
.setAge(42)
.setGender("male")
Though, I think the convention is to use withX rather than setX here.
Returning this allows chaining such as:
player.setName(...).setSomethingElse(...)
When returning void there is no object reference so chaining is not possible and you have code such as:
player.setName(...);
player.setSomethingElse(...);
I am wondering why one can ask how returning nothing and returning something could be the same. Anyway: no, returning something and returning nothing is not the same.
Returning this is mainly used to allow for "fluent" interfaces, so that users of your classes can write
yourObject.setFoo(foo).setBar(bar).doSomething();
instead of
yourObject.setFoo(foo);
yourObject.setBar(bar);
yourObject.doSomething();
If that helps with readability probably depends on the style you and the other people working with that source code are used to. One typical pattern that heavily relies on writing such code is the Builder pattern.

No arg constructor or arg constructor

In my program I read a fixed length file, stored each string in a local variable, and then stored every value into a class type array list. For creating the object of an array list, I used argument constructor with all the variables. The below code demonstrates this.
String a = "text1";
String b = "text2";
SampleModel sm = new SampleModel(a,b);
ArrayList<SampleModel> sampleList = new ArrayList<>();
sampleList.add(sm);
I find this absolutely right but my colleague asked me to change it to a no arg constructor and call getters and setters instead. That would be like below.
SampleModel sm = new SampleModel();
ArrayList<SampleModel> sampleList = new ArrayList<>();
String a = "text1";
String b = "text2";
sm.setA(a);
sm.setB(b);
sampleList.add(sm);
Is there any reason to prefer a no arg constructor over argument constructor? (My program has around 15 variables)
It depends on how the class will be used.
For example, an immutable class will need a constructor that takes arguments, and no setters.
But a Java Bean will need a no-argument constructor, and setters.
Some things to consider:
Encapsulation can be valuable. Other than special cases like JavaBeans, usually the interface of the class can be designed based on the desired interactions, not on the current set of data members.
Methods have names. Java does not support named arguments. Method names communicate how an actual parameter is being used, in the calling code. If your class has more than a handful of parameters, passing them via methods can result in more readable calling code.
Immutable classes have value. If you're adding named setters directly in your class, it won't be immutable. The builder pattern allows you to accept construction parameters even for immutable classes.
Whether I use accessors and mutators for a class variable depends on two things:
Whether the variable is essential or optional to the object.
Whether it might ever change in the course of using the object, or whether it is final.
Variables that are necessary and final should be in the constructor, in my opinion, and should not have mutators. Variables that are optional should have accessors and mutators. Variables that are essential but might change are up to your discretion. I would probably put them in the constructor, but use a Builder design pattern to avoid having a long list of arguments for the constructor.
A constructor that takes arguments is essentially for convenience (although that's not always the case if the object requires arguments in order to be constructed properly, it is here without seeing anymore context); it's doing the exact same thing as the set methods are doing.
There is no reason to not have a constructor take arguments, as long as those arguments "make sense" in the context of the object. In other words, it's more of a semantics thing to consider than a correctness thing.
If the constructor is:
public SampleModel(String a, String b)
{
this.a = a;
this.b = b;
}
It probably doesn't make a difference.
It might just be that it's easier to see whats going on than having a large comma separated list. This might also be a nice place to use Double Brace Initialization:
String a = "text1";
String b = "text2";
SampleModel sm = new SampleModel() {{
setA(a);
setB(b);
}};
ArrayList<SampleModel> sampleList = new ArrayList<>() {{
add(sm);
}};
Quotation from Fowler and Beck book: "Refactoring"
Long Parameter List
In our early programming days we were taught to pass in as parameters everything needed by a routine. This was understandable because the alternative was global data, and global data is evil and usually painful. Objects change this situation because if you don't have something you need, you can always ask another object to get it for you. Thus with objects you don't pass in everything the method needs; instead you pass enough so that the method can get to everything it needs. A lot of what a method needs is available on the method's host class. In object-oriented programs parameter lists tend to be much smaller than in traditional programs. This is good because long parameter lists are hard to understand, because they become inconsistent and difficult to use, and because you are forever changing them as you need more data. Most changes are removed by passing objects because you are much more likely to need to make only a couple of requests to get at a new piece of data. Use Replace Parameter with Method when you can get the data in one parameter by making a request of an object you already know about. This object might be a field or it might be another parameter. Use Preserve Whole Object to take a bunch of data gleaned from an object and replace it with the object itself. If you have several data items with no logical object, use Introduce Parameter Object. There is one important exception to making these changes. This is when you explicitly do not want to create a dependency from the called object to the larger object. In those cases unpacking data and sending it along as parameters is reasonable, but pay attention to the pain involved. If the parameter list is too long or changes too often, you need to rethink your dependency structure.

Java setting private fields inside constructors

Common design practice is to make instance variables private and have public getters and setters to access them. But many times I have seen code samples on the internet that have constructors that assign values directly to the private instance variable instead of using the setters inside constructors. Am I missing something?
public class Person{
private String name;
public Person(String name){
//is this right, seems like the whole encapsulation purpose is defeated
this.name = name;
//shouldn't this be used
setName(name);
}
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
}
You are not missing anything. What you do depends entirely on your situation. However, consider this:
It is very common to do parameter validation in a setter. For example, let's say I have a class with field that can hold a value 0 through 10 (the "throws" is unnecessary for the exception type below but I include it for clarity):
public class Example {
private int value;
public Example () {
}
public final int getValue () {
return value;
}
public final void setValue (int value) throws IllegalArgumentException {
if (value < 0 || value > 10)
throw new IllegalArgumentException("Value is out of range.");
}
}
Here, setValue() validates 'value' to make sure it sticks to the rules. We have an invariant that states "an Example will not exist with an out of range value". Now let's say we want to make a constructor that takes a value. You might do this:
public class Example {
...
public Example (int value) {
this.value = value;
}
...
}
As you can see, there is a problem. The statement new Example(11) would succeed, and now an Example exists that breaks our rules. However, if we use the setter in the constructor, we can conveniently add all parameter validation to the constructor as well:
public class Example {
...
public Example (int value) throws IllegalArgumentException {
setValue(value); // throws if out of range
}
...
}
So there are many benefits to this.
Now, there are still cases when you might want to assign values directly. For one, maybe you don't have setters available (although I would argue that creating private or package private setters is still desirable, for the reasons mentioned above, for reflection/bean support if necessary, and for ease of validation in more complex code).
Another reason might be that perhaps you have a constructor that knows, somehow, ahead of time that valid values will be assigned, and therefore doesn't need validation and can assign variables directly. This is usually not a compelling reason to skip using setters though.
However, all-in-all, it's generally a good idea to use the setters everywhere when possible, it will usually lead to cleaner and clearer code that is easier to maintain as complexity increases.
Most of the examples you see where people set variables directly are just people being "lazy" - which is perfectly acceptable if the situation warrants it (perhaps you're writing a quick test program or application and don't want to implement a bunch of setters, for example). There's nothing wrong with that as long as you keep the big picture in mind and only be "lazy" when it's appropriate.
Something I'd like to add based on some of the other answers here: If you override a setter in a subclass, and the data you are setting breaks invariants that the base class assumes, then either the relevant setters should be made final or the base class should not make those assumptions. If overriding setters breaks base class invariants then there is a bigger issue at hand.
You'll notice the getter/setter is final in the above example. This is because our rule is that "any Example must have a value from 0 to 10". This rule therefore extends to subclasses. If we did not have that rule and if an Example could take on any value, then we would not need a final setter and could allow subclasses to override.
Hope that helps.
Sometimes when you would want make the class immutable, it is just one of the things you need to do. And don't have setter methods at all in that case.
Depending on the context, the use of getters and setters is actually a bigger violation of encapsulation than using member variables in constructors. If you want to set the member variable 'name' of this class, either of these approaches would work since the construction is hidden from the caller and thus not violating encapsulation. One warning is that the use of setName within the constructor might call an overrided method in a subclass which may not be what you want (since it may leave name undefined in the superclass).
Here's a similar question to yours that may provide additional insight:
calling setters from a constructor
the private variables are accessible directly anywhere in the class
settng variabels private is to encapsulate them from other classes
Setting variables to private is to encourage encapsulation from other classes.
Unless setName(String) was meant to do something extra (which the method name doesn't imply), it's unnecessary to use the setter while you're in the class where the private variable is.
This does not defeat encapsulation since the private member is still hidden from the other classes
If the modifier method does not contain any logic and just sets the member then there is no difference between directly setting the member of calling its setter method although for better practice the setter should be called.
The setter indicates that this person's name might change in the future and allows it easily without creating an entire person object again.
Initializing variables inside constructor is a very common practice. It can be used to assign values to variables based on which constructor user has called. You cannot write code based on assumption that the client code will invoke setter method to assign value to instance variables. It is always safe to assign default value to a variable when its object is created (i.e inside constructor).
There is a difference between initializing variables within constructor and setting it to different value as per requirement of the calling code(using setter method). Both have different purposes and different objectives.
This is perfectly normal. Some variables might need to be initialized as soon as the object is created, hence it makes sense to pass them in the constructor and many times we may not want to provide setters for those variables to avoid changing the values after object is created.
Its ok to directly assign values with in class provided setter doesn't do any other processing.
Basically setters/getters are used to provide restrictive access to private data such as returning copy of the data instead of reference of private object, validating data in getter etc..
Since the constructor is part of the object itself, and we are sure what we are doing is right, then its ok.
My preferred approach (as described by Joshua Bloch in "Effective Java") is to make the constructor private, make the fields final (i.e., eliminate the setters entirely), and require clients to obtain instances either using the Builder Pattern or Factory Method Pattern, which would take care of any necessary validation to protect invariants. Then the (private) constructor would simply directly assign the given parameters (which have already been validated by the Builder or Factory Method) to the appropriate fields, which are private and final.

Can a Constructor Use a Builder

I am refactoring a class to use a builder with a private constructor instead of public constructors. I want to have the old, deprecated, public constructors use the builder as shown below. (this is an example of the behavior I am try to achieve)
// old public construcor
#Deprecated
public MyClazz(){
return new MyClazzBuilder().Build();
}
This give a "Cannot return a value from a method with void result type"
Is this type of functionality possible in Java? How could this be achieved?
Update: This code is part of a distributed jar, deleting the old constructors is not an option because I need to maintain backwards compatibility
No. Constructors operate on an object, they don't return it. [footnote 1]
One way to get this sort of functionality is with an init() method.
#Deprecated
public MyClazz() {
init();
}
public void init() {
// do the actual work
}
Now your builder can call the same init() method to avoid having the code in two places.
Because you are keeping the deprecated signatures around, it's hard to avoid splitting the logic for preparing an instance into multiple places. That's not ideal, but it's the price of deprecation and maintaining backwards compatibility.
[footnote 1] The lifecycle of a java object is that first the object memory is allocated, but all the fields have junk content. Next a constructor is run on the memory to get it into a consistent state by changing all those meaningless values into real values. Note that the memory the constructor works on is already there, so you can never substitute another object in place of the one being constructed. A return value from a constructor would be exactly this sort of substitution, which is not supported by the language. If that trick is needed use a factory/builder instead of a constructor -- constructors can never do that.
Constructors don't return values. Notice how there is no "declared" return type in a constructor signature. You have a few options:
1) Mark the constructor private and resolve compilation errors immediately
2) Deprecate the constructor, and leave the original implementation there.
I recommend number 2. What you have done is deprecate a constructor, and then changed the implementation. That is not how deprecation works.

Set, Get and Constructors in Java

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.

Categories