I have two classes Float2 && Double2
public final class Float2 {
public float width;
public float height;
public Float2 multiplyBy(float number) {
return new Float2(this.width * number, this.height * number);
}
}
public class Double2 {
public double width;
public double height;
}
I want to cast the result of multiplyBy method to a Double2 so that in the end I do not have Float2 newRectangleSize = rectangleSize.multiplyBy(3.2f); but Double2 newRectangleSize as the result of multiplication. Of course I can cast width and height values separately but I was wondering if there was a more ellegant solution in java?
If Double2 and Float2 would be related types then casting could be possible.
As long as they aren't, you cannot cast them regardless the names of parameters are same including their types. However, you can use this advantage for a framework based on reflection that makes mapping between types easy, such as MapStruct:
#Mapper
public interface Double2Mapper {
Double2Mapper INSTANCE = Mappers.getMapper(Double2Mapper.class);
#Mapping
Double2 floatToDouble(Float2 float2);
}
Double2 double2 = Double2Mapper.INSTANCE.floatToDouble(rectangleSize.multiplyBy(3.2f));
If you are not keen to use a framework (in case of only few specific and simple cases), I offer you two basic ways based on the pure OOP:
A constructor of Double2 using Float2 (assuming the fields remain public):
public Double2(Float2 float2) {
this.width = float2.width;
this.height = float2.height;
}
A method returning such type in the class Float2:
public Double2 asDouble2() {
return new Double2(this.width, this.height);
}
So clearly trying to cast in this case will result in a ClassCastException. One option would be to support an interface that is implemented by both classes that allows width() and height() to be defined as Number objects or even a type that extends Number. Then you could handle conversion on a implementation by implementation basis to handle precision loss in cases like int or short.
interface Size<T extends Number> {
T width();
T height();
}
Another option might be to provide static factory methods to these classes to allow for the conversion of Double2 to Float2 and vice versa. It might look like this;
public class Double2 {
private final double width;
private final double height;
public Double2(double width, double height) {
this.width = width;
this.height = height;
}
public static Double2 valueOf(Float2 float) {
return new Double2((double) float.width, (double) float.height);
}
}
Float2 float2 = new Float2(2f, 2f).multiplyBy(2f);
Double2 double2 = Double2.valueOf(float2);
Related
So I'm extending the Java Rectangle class. And I happen to be a bit confused with the use of this and super and when each should be used. I understand that super is the super class (parent class) and this is the current class you're calling it from.
I currently have a BetterRectangle class extending from the Rectangle class and a method:
boolean isCongruent(Rectangle r)
{
if(r.width == super.width && r.height == super.height)
{
return true;
}
return false;
}
Does it matter if I use this.width and this.height instead of super?
Which would be the more correct way of using regardless both give me the same answer?
If your subclass has field width (and height), then super.width's value can be different than this.width depending on how you initialize the fields. Here is a quick test:-
import java.awt.*;
public class BetterRectangle extends Rectangle {
public int width;
void testWidth() {
System.out.println("width = " + width);
System.out.println("this.width = " + this.width);
System.out.println("super.width = " + super.width);
}
}
--
public static void main(String[] args) {
Rectangle rect = new BetterRectangle();
rect.width = 10; //sets the value of super class's field
((BetterRectangle) rect).width = 90; //sets the value of subclass's field
((BetterRectangle) rect).testWidth();
}
This prints:-
width = 90
this.width = 90
super.width = 10
Note that width and this.width prints the same thing because of data hiding. You'll have to add the super keyword to access the super class's field.
If you don't have a width variable in your subclass, then super.width and this.width point to the same field, so why not just use width?
Hope this helps.
Does it matter if I use this.width and this.height instead of super?
If your subclass has inherited the attributes from its superclass (in this case, Rectangle's width and height), then your subclass now owns width and height as its own attributes.
So if your intention is to access the subclass' attributes, using this (which refers to the class itself) will make more sense isn't it? So I will go with using this.
Attributes inherited to child:
class Parent{
protected int width = 5;
protected int height = 5;
}
class Child extends Parent{
public Child(int width, int height){
this.width = width;
this.height = height;
}
public int getHeight() {
return this.height;
}
public int getWidth() {
return this.width;
}
public int getSuperHeight() {
return super.height;
}
public int getSuperWidth() {
return super.width;
}
}
Test Run:
Child c = new Child(2, 3);
System.out.println(c.getWidth() + " " + c.getHeight()); //2 3
System.out.println(c.getSuperWidth() + " " + c.getSuperHeight()); //2 3
Like what ScarryWombat mentioned, if the attributes are masked by the attributes declared in the subclass, then using this and super makes a difference. this now refers to the attributes declared within the subclass instead of the inherited attributes.
Attributes inherited to child, but masked:
class Child extends Parent{
private int width;
private int height;
public Child(int width, int height){
this.width = width;
this.height = height;
}
public int getHeight() {
return this.height;
}
public int getWidth() {
return this.width;
}
public int getSuperHeight() {
return super.height;
}
public int getSuperWidth() {
return super.width;
}
}
Test Run:
Child c = new Child(2, 3);
System.out.println(c.getWidth() + " " + c.getHeight()); //2 3
System.out.println(c.getSuperWidth() + " " + c.getSuperHeight()); //5 5
In general, there should hardly ever be a genuine need to use either this. or super.
Looking at your iscongruent() method, ask yourself how it could ever return false. Answer : that's only possible if the super class and the sub class both have a member of the same name, that is, there are multiple distinc fields named 'width' and/or 'height'. That's bad practice.
Why is that so ? Suppose these fields are supposed to carry the same semantics. At all time. So then why are there two distinct appearances of the field ? It's plain redundancy and that's a source of bugs. Eliminate one of the two and you're out of the problem. Suppose contrariwise that these fields can possibly carry different semantics. You likely want to expose those semantics in your sub class at least through a getter (and perhaps a setter too). So now you have getters (and perhaps setters) in both your super and sub classes with identical signatures but differing semantics. That's plain anti-design-by-contract. Sub classes should never alter the semantics of methods established by their super class. And finally, if you don't want to expose the same-named field in the sub class, there's nothing to stop you from just naming it 'localWidth' or 'subWidth' or whatever other name that provides a better and more detailed explanation of the intended semantics.
That said, here are some cases where using 'this' and/or 'super' is warranted or even unavoidable :
In constructors, when setting fields from the value of a parameter that has been given the same name as the field :
this.x = x; /* x = x would mean an assignment to the method parameter, not the field */
In overriding implementations, when you also need to execute the code as defined in the super class :
method ( ... ) {
super.method( ... );
/* some extra code here to deal with the extra state in the sub class */
}
There may be more, but in general abundant use of 'this' and 'super' leads to too much 'noise' that can be avoided without harming readability. Of course that's just a matter of opinion and of preferred style.
The best way may be is to look at how standard Java classes accesses the variables. javax.swing.text.DefaultCaret extends Rectangle. Except where there are local variable clashes - the access of variables do not use any this or super specifiers. I would stick to that :).
For example, this is the repaint method:
protected final synchronized void repaint() {
if (component != null) {
component.repaint(x, y, width, height);
}
}
I want to make a two-dimensional vector that is holding two numeric values.
As usual vectors (even of different numerical type) should e.g. be addable.
In C++ you can just do something like:
template<typename T>
class vector2d{
T x{0};
T y{0};
public:
template<typename U> vector2d& operator+=(const vector2d<U>& vec){
x += vec.x;
y += vec.y;
return *this;
}
...
template<typename U>
friend class vector2d;
};
But when I try to achieve this in Java I am coming across some problems.
Here is what I tried to do:
class vector2d<T extends Number>{
private T x;
private T y;
public <U extends Number> vector2d add(vector2d<U> vec){
x += vec.x;
y += vec.y;
return this;
}
...
}
But this does not work. It would if i would use Integer or Float or whatever directly (because of Autoboxing). But this seems not to be the case when you just use the Number class directly. As I think there is no other interface that would satisfy the requirements, I am kind of stuck here.
So my question is if there are ways to make this work in Java.
One of possibilities to achieve this, is use BigDecimal class:
class vector2d{
private BigDecimal x;
private BigDecimal y;
public void add(vector2d vec){
x = x.add(vec.x);
y = y.add(vec.y);
}
...
}
But it can reduce performance of your code, as its operations aren't very fast.
You can also keep Number class and use doubleValue always:
class vector2d{
private Number x;
private Number y;
...
public void add(vector2d vec){
x = x.doubleValue() + vec.x.doubleValue();
y = y.doubleValue() + vec.y.doubleValue();
}
}
this will allow use any types of numbers:
vector2d v1 = new vector2d(1, 2.3);
vector2d v2 = new vector2d(1.3, 2);
v1.add(v2);
UPD: As #Jesper has mentioned, instead of Number just double type can be used, which will eliminate need of .doubleValue() invocation. So you have various way to do it.
Suppose I have class with 2 fields: x and y, of type double. Is it possible to define 2 constructors so constructor1 will create object setting its x property to what parameter in constructor tell and y to default and constructor2 vice versa?
public class Test {
private int x;
private int y;
public Test(int x) {
this.x = x;
}
public Test(int y) {
this.y = y;
}
}
I'm trying something like that and I know that it wont work because of overloading rules
No, you can't do that. Typically you'd do something like:
private Test(int x, int y) {
this.x = x;
this.y = y;
}
public static Test fromX(int x) {
return new Test(x, 0);
}
public static Test fromY(int y) {
return new Test(0, y);
}
You might want to consider that pattern (public static factory methods which in turn call private constructors) even when you don't have overloading issues - it makes it clear what the meaning of the value you're passing is meant to be.
No, You cannot have two methods or constructors with the same signature. What you can do is have named static factories.
public class Test {
private int x;
private int y;
private Test(int x, int y) {
this.x = x;
this.y = y;
}
public static Test x(int x) { return new Test(x, 0); }
public static Test y(int y) { return new Test(0, y); }
}
Test x1 = Test.x(1);
Test y2 = Test.y(2);
No, x and y have identical types, so both constructors would have the same type signature and the method resolution is based on parameter type, not name; the compiler has no way of differentiation.
The compiler looks for "Test.Test(int)" regardless of what the name of the parameter is.
The language would need additional feature added, such as named parameters, to do what you want.
If Java ever gets a syntax like C# for property initialization, you'll be able to use that idiom, using a default no-args constructor.
Besides the alternatives of using explicit factory methods, you could pass in a HashMap for your parameters.
public Test(HashMap<string,int> args) {
if(args.containsKey("x"))
x = args.get("x");
if(args.containsKey("y"))
y = args.get("y");
}
But static factory methods are cleaner for most cases. If you need much more, you may need to consider why you need such an idiom in the first place, and revise your class design.
How the enum that we get from java 1.5 is different from C++ and other conventional Enum Type.
In java enums are complex objects, whilst in C++ every enum object is associated with a single integer value. In java you can have several attributes associated with a single enum value:
enum MyCategory {
SPORT("The sport category", "sport.png"),
NEWS("the news category", "news.jpg");
private String description;
private String iconPath;
private MyCategory(String description, String iconPath) {
this.description = description;
this.iconPath = iconPath;
}
public String getDescription() {
return description;
}
public String getIconPath() {
return iconPath;
}
}
Furthermore in java you can switch only Number types, Strings and enums. However I can not generalize the conventional enums as a whole...
EDIT One more thing the java enums can do is declare per-value operation (taken from the java tutorial):
public enum Operation {
PLUS { double eval(double x, double y) { return x + y; } },
MINUS { double eval(double x, double y) { return x - y; } },
TIMES { double eval(double x, double y) { return x * y; } },
DIVIDE { double eval(double x, double y) { return x / y; } };
// Do arithmetic op represented by this constant
abstract double eval(double x, double y);
}
Java programming language enums are far more powerful than their counterparts in other languages, which are little more than glorified integers. The new enum declaration defines a full-fledged class (dubbed an enum type). In addition to solving all the problems(Not typesafe, No namespace, Brittleness and Printed values are uninformative) that exists with following int Enum pattern which was used prior to java 5.0 :
public static final int SEASON_WINTER = 0;
it also allows you to add arbitrary methods and fields to an enum type, to implement arbitrary interfaces, and more. Enum types provide high-quality implementations of all the Object methods. They are Comparable and Serializable, and the serial form is designed to withstand arbitrary changes in the enum type.
Read the full article Java Enums for more details.
If I have an enum object, is it considered a primitive or a reference?
It's a reference type. Java primitives are boolean byte short char int long float double.
You can get the enumeration constant's value by calling ordinal(), which is used by EnumSet and EnumMap iterator and "traverses the elements in their natural order (the order in which the enum constants are declared)"
You can even add your own members to the enum class, like this:
public enum Operation {
PLUS { double eval(double x, double y) { return x + y; } },
MINUS { double eval(double x, double y) { return x - y; } },
TIMES { double eval(double x, double y) { return x * y; } },
DIVIDE { double eval(double x, double y) { return x / y; } };
// Do arithmetic op represented by this constant
abstract double eval(double x, double y);
}
//Elsewhere:
Operation op = Operation.PLUS;
double two = op.eval(1, 1);
The way enums work is actually not too different from how they were used before their introduction with Java 5:
public final class Suit {
public static final Suit CLUBS = new Suit();
public static final Suit DIAMONDS = new Suit();
public static final Suit HEARTS = new Suit();
public static final Suit SPADES = new Suit();
/**
* Prevent external instantiation.
*/
private Suit() {
// No implementation
}}
By instantiating the different suits on class loading it is ensured that these will be mutually exclusive and the private constructor ensures that no further instances will be created.
These would be comparable either through == or equals.
The Java 5 enum works pretty much the same way, but with some necessary features to support serialization etc.
I hope this background sheds some further light.
This article essentially shows you how enums are implemented, and as SLaks says, they are references.
Enums are reference types, in that they can have methods and can be executed from command line as well , if they have main method.
See following "Planet" example from Sun/Oracle
http://download.oracle.com/javase/tutorial/java/javaOO/enum.html