First please understand that I may have this totally wrong which is why google isn't help.
I am trying to construct the following object: M3Tools
public class M3UTrack {
private String path;
private int secondsDuration;
private String label;
//Get and set of these omitted
public M3UTrack()
{
path = null;
label = null;
secondsDuration = 0;
}
public M3UTrack(M3UTrack t)
{
// Creating a track as a duplicate of the track you pass it?
path = new String(t.getPath());
label = new String(t.getLabel());
secondsDuration = t.getSecondsDuration();
}
From what I gather if I was to use the second constructor I would have to pass an object of itself??? It's throwing me in a loop. There are other classes involved.
The M3UTrack(M3UTrack t) is a so called copy constructor, because it creates a new instance but copies the values of the other. If you want to create a first/new instance you would probably use the first version. The class and constructor are public, so nothing should stop you from writing
M3UTrack t = new M3UTrack(); // default constructor
t.setPath(...); t.setLabel(...); t.setDurationSeconds(10); // fill data
M3UTrack s = new M3UTrack(t); // sample usage of copy constructor
If you have problems with this you need to show us your code and your error message. It is a compile time or runtime error? If it is a stacktrace please also tell us which line numbers are involved.
BTW: you might want to add another constructor which alles to specify all mandatory fields, so you dont need to use the setters. This has the advantage that you never have a "half" constructed object. When you omit the setters then you are using a pattern called immutable object:
public M3UTrack(String path, String label, int duration)
{
this.path = path;
this.label = label;
this.secondsDuration = duration;
}
And then construct it like:
M3UTrack t = new M3UTrack("file.mp3", "Songs", 10/*sec*/);
You can perfectly reference an object of a class you are defining. If not, how could you create copy constructors? which, by the way, is exactly what you are doing at public M3UTrack(M3UTrack t).
From Wikipedia:
Copy constructors define the actions performed by the compiler when
copying class objects. A copy constructor has one formal parameter
that is the type of the class (the parameter may be a reference to an
object)...
From what it looks like, you'd construct an instance of M3Track and set the properties on it. If you want to make a copy, you have the given copy constructor as an option.
This construct has name "copy constructor"and is used in specyfic places. Normal use first, no arguments construcror.
Usage of copy constructor, like name says, is "between" two objects (old and new), seems Your use case never occur (sorry for spelling, this from phone)
M3UTrack theNew = new M3UTrack(theOld)
Related
I have the following class:
package com.tesco.demandforecasting.group8.choprachap7;
import java.util.ArrayList;
import com.tesco.demandforecasting.group8.utils.MathOperUtils;
import com.tesco.demandforecasting.group8.utils.RegressionUtils;
import lombok.Getter;
/**
* This class if used to find seasonality factor of each period, as explain in
* the chapter See https://kelley.iu.edu/mabert/e730/Chopra-Chap-7.pdf for the
* explanation
*/
#Getter
public class ChopraChap7SeasonalFactorsCalculator {
private double[] regressionParams;
private int sales_size;
private int periodicity;
private ArrayList<Integer> sales;
private ArrayList<Double> deseasonalisedData;
private ArrayList<Double> deseasonalisedDemandUsingRegression;
private ArrayList<Double> seasonalityFactors;
public ChopraChap7SeasonalFactorsCalculator() {
this.sales = new ArrayList<>();
this.deseasonalisedData = new ArrayList<>();
this.deseasonalisedDemandUsingRegression = new ArrayList<>();
this.seasonalityFactors = new ArrayList<>();
this.sales.add(8000);
this.sales.add(13000);
this.sales.add(23000);
this.sales.add(34000);
this.sales.add(10000);
this.sales.add(18000);
this.sales.add(23000);
this.sales.add(38000);
this.sales.add(12000);
this.sales.add(13000);
this.sales.add(32000);
this.sales.add(41000);
this.sales_size = sales.size();
this.periodicity = 4;
calculateSeasonalityFactors();
}
private void calculateSeasonalityFactors() {
.......
.......
this.seasonalityFactors = seasonalityFactors;
this.deseasonalisedDemandUsingRegression = deseasonalisedDemandUsingRegression;
this.deseasonalisedData = deseasonalisedData;
}
}
I want to expose the class fields to external classes, using their respective getters. But, the problem is that those fields attain any value only after the ChopraChap7SeasonalFactorsCalculator() method is called. So, what I have done here is call the method as soon as an object of the class is created. Of course, this will work, but is this good design pattern?
Supposing I would not have called the method from the constructor. So, if we have the following code is some other class:
ChopraChap7SeasonalFactorsCalculator calc = new ChopraChap7SeasonalFactorsCalculator();
calc.getDeseasonalisedData();
This will return to me any empty array list. How do I ensure that the method is called before any field is accessed?
What would be the best design pattern in my case?
Of course, this will work, but is this good design pattern?
This is a very correct design. You delegate a part of the constructor logic into a private method to make things clearer.
This will return to me any empty array list. How do I ensure that the
method is called before any field is accessed?
Your fear about someone changes something in the constructor may be true for any methods or chunks of code.
But applications are not designed to check that each component does what we expect from it. This is the unit tests role to assert that the actual behavior is which one expected.
So write an unit test for the ChopraChap7SeasonalFactorsCalculator constructor and in this test assert that all getters return the expected values once the object is created.
If someone modifies the constructor in an incorrect way, the test will fail and the build too. You have your way to make sure things are as expected now.
I think that's pretty fine. The constructor is there to create a useful object. If you are sure the object cannot be used without these being set there is no reason why not to set them in the constructor.
If you check https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
A class contains constructors that are invoked to create objects from
the class blueprint.
You have added the fields but you don't have a working object without these being set and apparently you know the values already. The best way to do it would be leave these in the constructor. If there are some unknown values or requirements in order to create an instance of that class you can consider Factory pattern or something but in your case constructor usage is just fine.
Java allows to summarize this.classVar = parameter; this.classVar2 = parameter2; expressions to this(parameter, parameter2). At least used in a constructor.
But this code doesn't work when I change from the former way (commented in the code) to the latter way in a setter:
class Client {
String nombre, apellidos, residencia;
double comision;
void setClient(String nombre, String apellidos, String residencia, double comision){
this(nombre, apellidos, residencia, comision);
//this.nombre = nombre;
//this.apellidos = apellidos;
//this.residencia = residencia;
//this.comision = comision;
}
}
Error says:
"call to this must be first statement in the constructor.
Constructor in class Client cannot be applied to given types.
required: no arguments
<p>found: String, String, String, double
<p>reason: actual and formal argument list differ in length" (I haven't created one, just left the default).
So, is this way of using 'this' only valid for constructors, and therefore not suitable for setters? Does it require to explicitly code the constructor (if so, why?)?
Java allows to summarize this.classVar = parameter; this.classVar2 = parameter2; expressions to this(parameter, parameter2).
No, it doesn't. You still have to code the this.classVar = parameter; this.classVar2 = parameter2; somewhere. All this(parameter, parameter2) does is call a constructor (which would have to have the this.classVar = parameter; this.classVar2 = parameter2; code in it, if those parameters were going to be written to those fields).
You can't call the constructor from a setter. You can only call a constructor from within a constructor. It's used to consolidate logic in a single constructor even when you have more than one with varying parameters, for example:
public MyContainer(int size) {
this.size = size;
}
public MyContainer() {
this(16);
}
There, the zero-parameters version of the MyContainer constructor calls the single-parameter version, passing it 16 for the size parameter.
this(nombre, apellidos, residencia, comision) doesn't "summarize" anything.
It's just a way to call another constructor in the class from a constructor.
There is no way to "summarize" anything
this(/* zero or more args */);
This is a constructor call. You can use it from one constructor to refer to another (for lack of a better name, 'constructor chaining').
You cannot do the same thing from a normal method. If you want to create an object from within a normal method, you use the same syntax as you'd use an an external user of the class:
new MyClass(/* args */);
From your code, it doesn't look like this is the approach you'd want to take.
Recently on the interview I had an interesting question.
We have mutable class:
final class Example {
private int i;
private String s;
private Object o;
// get, set
}
And instance of this class Example e = new Example();
Can we somehow make this instance immutable? Without changing original class.
My thoughts:
Deep cloning of this instance? But not sure if it's possible.
Maybe something like serialization/deserialization?
If you are unable to make modifications to the Example class and you cannot subclass it (in your snippet, it is marked as final) the closest solution I can think of is to create a wrapper class, which is immutable. This is not a perfect solution, and has it's drawbacks.
First, how to do it:
final class ImmutableExample {
// Redeclare every field as in the Example class
// but make sure they can't be reassigned
// (in this case I'll declare them as final)
private final int i;
private final String s;
private final Object o;
ImmutableExample(Example mutableExample) {
// copy fields from original
this.i = mutableExample.getI();
this.s = mutableExample.getS();
this.o = mutableExample.getO();
}
// add getters but definitely no setters
}
Then everywhere you have code like this:
Example e = new Example();
e.setI(42); // etc
Change to:
Example e = new Example();
e.setI(42); // etc
ImmutableExample immutableE = new ImmutableExample(e);
And pass around references to immutableE, and make sure that the e reference does not escape.
Now, for the drawbacks:
ImmutableExample is not an instance of Example, so you cannot pass the immutable type to a method which expects the mutable type, and operations like if (immutableE instanceof Example) or (Example)immutableE will not work as before
You have to be very careful that every field of Example is also immutable, or ImmutableExample will also be mutable. Consider, for example, that the field of type Object could be something mutable, like a HashMap or a Date.
When the Example class changes, you have to repeat the change in ImmutableExample.
If it was possible to subclass Example, or if it was an interface, this approach might be more useful, but I can't see any other way when Example cannot be subclassed.
If each of those fields have getters/setters, then to make it immutable, you will have to
Make each field private and final
Make a copy of each field when it's getter is called
Remove all setters
Any methods within the class that changes it's state must either be removed or use the new getters to access any internals
Immutability is a property of a class not an instance. So besides bytecode twiddling or other means to change the class; not possible.
With a none final class i would create an immutable decorator. That would not make the instance immutable, but provide an immutable wrapper to that instance.
You could not assign the instance to any variable/field, making it impossible to change it ;)
I have the following, stripped-down Java code:
// Class, in it's own file
import java.util.*;
public class Superclass {
protected List<Subclass> instances = new ArrayList<>();
public class Subclass extends Superclass {
private int someField;
public Subclass(int someValue) {
this.someField = someValue;
updateSuperclass();
}
private void updateSuperclass() {
super.instances.add(this);
}
}
}
// Implementation, somewhere else, everything has been imported properly
Superclass big = new Superclass();
Subclass little1 = big.new Subclass(1);
Subclass little2 = big.new Subclass(2);
Subclass little3 = big.new Subclass(3);
I want to implement a method in Superclass to do something with all the Subclasses. When a Subclass is created, it should add itself to a list in Superclass, but whenever I try to loop through that list in Superclass, it says the size is 1. The first element in the list (instances.get(0)) just spits out a String with all the proper information, but not in object form, and not separately. It's like every time I go to add to the list, it gets appended to the first (or zeroeth) element in String form.
How can I solve this so I can maintain an ArrayList of Subclasses to later loop over and run methods from? I'm definitely a beginner at Java, which doesn't help my case.
If all you need is a count then I suggest a static value that is updated in the constructor of the parent class.
private static int instanceCount = 0;
public Constructor() {
instanceCount++;
}
If you absolutely need every instance in a list so you can do something with them then I recommend you strongly re-consider your design.
You can always create a utility class that will let you maintain the list of objects to run processes on. It's more "Object Oriented" that way. You can also create one class that has all of the operations and then a simpler bean class that has only the data values.
But, if you insist, you can still use the same technique.
private static List<SuperClass> list = new LinkedList<SuperClass>;
public Constructor() {
list.add(this)
}
Each instance gets its own copy of your superclass's variables.
What you want to do is make the variable "static" by putting the static keyword before it. You probably don't even need the superclass accomplish what you're trying to do.
I have a class with name "ConstituentSet". it has one method namely "getNucleusInConstSet()" which the output will be from "Proposition" class . The new Class "Proposition" have another method namely "getProperty()". I want to know what is the Propertry of my "Proposition Nucleus" in class "ConstituentSet". but i do not know how can i do that.
I wrote as follow but It does not work. (ConstituentSet.getNucleusInConstSet()).getProperty())
public class ConstituentSet{
// Constructor
private Proposition nucleusInConstSet;
public Proposition getNucleusInConstSet() {
return nucleusInConstSet;
}
}
public class Proposition{
//Constructor
private Property property;
public Property getProperty() {
return this.type;
}
}
You have:
(ConstituentSet.getNucleusInConstSet()).getProperty()
But you need to call an instance of ConstituentSet
e.g.
ConstituentSet cs = new ConstituentSet();
cs.getNucleusInConstSet().getProperty();
Note that this idiom (chained method calls) can be a pain. If one of your methods returns null, it's difficult to understand which one it is (without using a debugger). Note also that invocations of the form a().b().c().d() are a subtle form of broken encapsulation (a reveals that it has a b, that reveals it has a c etc.)
if you type ((ConstituentSet.getNucleusInConstSet()).getProperty()) you are attempting to call a static method of ConstituentSet.
You need to instantiate it and then call on that object.
ConstituentSet anInstanceOf = new ConstituentSet();
anInstanceOf.getNucleusInConstSet()).getProperty());
This won't work:
ConstituentSet.getNucleusInConstSet().getProperty();
Because the getNucleusInConstSet() method is not static. You have to use an instance of ConstituentSet, something like this:
ConstituentSet cs = new ConstituentSet();
cs.getNucleusInConstSet().getProperty();
Of course, you have to make sure that nucleusInConstSet is not null, or you'll get a NullPointerException. Initialize its value in ConstituentSet's constructor or set it using setNucleusInConstSet().
Alternatively, you could make getNucleusInConstSet() static, but I don't think that's the right thing to do in this case (but we don't have enough information about the problem to say so).