i have an immutable object that has weight as int, in my code, i need to update the weight, inroder to do that, i need to make a copy of that object and set the weight with updated value. but the object doesn't have a clone() override, and i don't know which way is better, clone() or implement Cloneable interface?
here is my class:
public class WeightedEdge implements Edge {
private final WeightedEdgeComparator _weightedEdgeComparator;
private final Vertex _target;
private final int _weight;
WeightedEdge(Bundle bundle, Vertex target, int weight) {
_weightedEdgeComparator = new EdgeComparator(bundle.getDirection());
_target = target;
_weight = weight;
}
@Override
public Vertex target() {
return _target;
}
@Override
public int weight() {
return _weight;
}
@Override
public int compareTo(WeightedEdge o) {
return _EdgeComparator.compare(this, o);
}
@Override
public int hashCode() {...}
@Override
public boolean equals(Object obj) { ... }
@Override
public String toString() { ... }
How about just returning a new object with the new value:
// as mentioned by AndrewBissell, there is no reference to the bundle
// luckily, we only need the direction from the bundle :)
private final int _direction;
WeightedEdge(Bundle bundle, Vertex target, int weight) {
this(bundle.getDirection(), target, weight);
}
WeightedEdge(int direction, Vertex target, int weight)
{
_direction = direction;
_weightedEdgeComparator = new EdgeComparator(_direction);
_target = target;
_weight = weight;
}
WeightedEdge updatedObject(int newWeight)
{
return new WeightedEdge(_direction, _target, newWeight);
}
You can use another constructor to clone your object, and update only the weight part.
WeightedEdge(WeightedEdge wEdge, int weight) {
//copy all fields of wEdge into THIS object, except weight.
//use int weight parameter to set the new weight
}
hth
Rather than pass the Bundle
or possibly a direction into the constructor solely for the purpose of using them to instantiate an EdgeComparator
in the constructor, simply make the EdgeComparator
the constructor argument, and store a reference to a cloned instance of it it in a field on WeightedEdge
:
WeightedEdge(EdgeComparator comparator, Vertex target, int weight) {
_weightedEdgeComparator = comparator.clone();
_target = target;
_weight = weight;
}
Then you can have WeightedEdge
implement Cloneable
and you will be able to provide all the necessary arguments when constructing the clone. This also allows you to separate your decision about EdgeComparator
implementations from your WeightedEdge
implementation, which is good OO practice.
Also, you need to make sure that all instances of Vertex
are immutable or it will be possible to construct a mutable instance of this class by passing a mutable target
into it. Alternatively, you could clone target
in the constructor as well.
If the EdgeComparator
is not cloneable, then there is no alternative to providing a constructor which accepts and stores a reference to the direction as shown in Binyamin Sharet's answer.
i have an immutable object that has weight as int, in my code, i need to update the weight, inroder to do that, i need to make a copy of that object and set the weight with updated value. but the object doesn't have a clone() override, and i don't know which way is better, clone() or implement Cloneable interface?
here is my class:
public class WeightedEdge implements Edge {
private final WeightedEdgeComparator _weightedEdgeComparator;
private final Vertex _target;
private final int _weight;
WeightedEdge(Bundle bundle, Vertex target, int weight) {
_weightedEdgeComparator = new EdgeComparator(bundle.getDirection());
_target = target;
_weight = weight;
}
@Override
public Vertex target() {
return _target;
}
@Override
public int weight() {
return _weight;
}
@Override
public int compareTo(WeightedEdge o) {
return _EdgeComparator.compare(this, o);
}
@Override
public int hashCode() {...}
@Override
public boolean equals(Object obj) { ... }
@Override
public String toString() { ... }
How about just returning a new object with the new value:
// as mentioned by AndrewBissell, there is no reference to the bundle
// luckily, we only need the direction from the bundle :)
private final int _direction;
WeightedEdge(Bundle bundle, Vertex target, int weight) {
this(bundle.getDirection(), target, weight);
}
WeightedEdge(int direction, Vertex target, int weight)
{
_direction = direction;
_weightedEdgeComparator = new EdgeComparator(_direction);
_target = target;
_weight = weight;
}
WeightedEdge updatedObject(int newWeight)
{
return new WeightedEdge(_direction, _target, newWeight);
}
You can use another constructor to clone your object, and update only the weight part.
WeightedEdge(WeightedEdge wEdge, int weight) {
//copy all fields of wEdge into THIS object, except weight.
//use int weight parameter to set the new weight
}
hth
Rather than pass the Bundle
or possibly a direction into the constructor solely for the purpose of using them to instantiate an EdgeComparator
in the constructor, simply make the EdgeComparator
the constructor argument, and store a reference to a cloned instance of it it in a field on WeightedEdge
:
WeightedEdge(EdgeComparator comparator, Vertex target, int weight) {
_weightedEdgeComparator = comparator.clone();
_target = target;
_weight = weight;
}
Then you can have WeightedEdge
implement Cloneable
and you will be able to provide all the necessary arguments when constructing the clone. This also allows you to separate your decision about EdgeComparator
implementations from your WeightedEdge
implementation, which is good OO practice.
Also, you need to make sure that all instances of Vertex
are immutable or it will be possible to construct a mutable instance of this class by passing a mutable target
into it. Alternatively, you could clone target
in the constructor as well.
If the EdgeComparator
is not cloneable, then there is no alternative to providing a constructor which accepts and stores a reference to the direction as shown in Binyamin Sharet's answer.
0 commentaires:
Enregistrer un commentaire