5

I have a Java class that has a few members. I want to write a custom cast for it. I was wondering how is it possible to do so?

Let's assume the class is as follows:

class Person {
   private int age;
   private float weight;

   // getters and setters and etc
}

I would like the int cast to return the member age of an object, and the float cast to return the weight of an object.

For instance:

public class Main {
    public static void main(String[] args) {

        // create an object
        Person P = new Person();
        P.setAge(21);
        P.setWeight(88.0);

        // case 1: casting object to an existing data type
        int personAge = (int) P; // would return the age
        float personWeight = (float) P;  // would return the weight

        // case 2: casting an existing data type to an object
        Person P2 = (Person) personAge; // this would create an instance of the object whose age is assigned and weight is not assigned

    }
}

I was wondering if it is possible to do the opposite. In particular, casting int to Person would return an instance of Person that its age is assigned and similarly for float.

I know this question may not have an answer. But because I did not find any useful results in my search, I decided to ask it.

P.S. I understand that for a String, the toString method would take care of case 1.

orezvani
  • 3,595
  • 8
  • 43
  • 57
  • 1
    You can't define new cast operations. The existing ones are all defined in the JLS. You can add methods like `toInt`, `fromInt`, `toFloat` and `fromFloat` though. – Sweeper Jun 06 '19 at 09:04
  • Casting can be done only for value to value but in your case Object has many fields, how casting will understand that it has to do for age only ? As @Sweeper said, you can do like that, however what is the need as we can have getter and setter methods. – Sambit Jun 06 '19 at 09:07
  • You may want to use Groovy for such cases (assuming the cast caller will be in groovy too). Otherwise you can implement `asInt`, `asFloat`... methods – ernest_k Jun 06 '19 at 09:07
  • Although its not allowed. Even if it's allowed, don't you think its quite confusing to map values with appropriate castings? – Himanshu Bhardwaj Jun 06 '19 at 09:09
  • @Sambit: Actually, it doesn't matter if the class has many members of the same type because I wanted to implement/overload the cast so that it decides which one to return. – orezvani Jun 06 '19 at 09:14

3 Answers3

6

You can't overload the cast operator. Java doesn't support it and probably never will.

To convert a single value to an instance of the desired class, we use static factory methods.

public static Person fromAge(int age) {
    return new Person(age);
}

They often return a partially constructed object. In the snippet above, a newly constructed person has only age set: other fields will have their default values.

To do the opposite, we use getters.

public int getAge() {
    return age;
}

However, since toString is already there, it makes sense to add other data types as well.

toInt makes no sense when it's applied to me (as an instance of the Person class). It could be my height, my weight, my age, a number of times I went to a bathroom today, etc. I can't represent myself by one int number, neither can a large majority of classes.

On the other hand, toString can do this job pretty well: I can give you (read return) a summary of my hobbies, my biometric information, even my picture. Or I can leave it to the default implementation, which still would satisfactorily represent an object.

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
  • So, it is not possible. However, since `toString` is already there, it makes sense to add other data types as well. – orezvani Jun 06 '19 at 09:19
  • @orezvani what data types do you want to add? – Andrew Tobilko Jun 06 '19 at 09:23
  • @orezvani the toString method is only there to help with logging/debugging. It prints a nice representation of your object. I don't think that it does make sense to add other data types (other than the way specified in this answer). If you had multiple field of type int then a toInt method wouldn't make sense, it is better to just have an accessor method for each of your fields – user27158 Jun 06 '19 at 09:29
  • @orezvani everything can be "textually represented" (as a `String`), but it's not true for any other type – Andrew Tobilko Jun 06 '19 at 09:35
  • 1
    @orezvani `toInt` makes no sense when it's applied to me (as an instance of the `Person` class). It could be my height, my weight, my age, a number of times I went to a bathroom today, etc. I can't represent myself by one `int` number. On the other hand, `toString` can do this work pretty well: I can give you (read *return*) a summary of my hobbies, my biometric information, even my picture. – Andrew Tobilko Jun 06 '19 at 09:42
  • Actually ... "[`toString`] prints a nice representation of your object" ... only if you have implemented it to do that. The default implementation (in Object) prints an ugly representation that *doesn't* tell you anything about the object's state other than its class name. – Stephen C Jun 07 '19 at 01:28
  • @StephenC Though it's ugly unless overridden, it still represents an object by its hash and class name. In case of `toFloat`, it would be a random number or `.0f`: both make no sense. – Andrew Tobilko Jun 07 '19 at 07:27
  • 1
    I'm not disputing that `toFloat` would be meaningless. What I am saying is that `Object::toString` is not a nice representation, and for many (naive) uses it is not a meaningful representation ... as illustrated by many SO questions about printing arrays, for example. (Something is only meaningful when people understand the meaning ...) – Stephen C Jun 07 '19 at 07:55
0

You wouldn't use a cast for this just write methods in your Person class to get those values.

public int getAge()
{
  return age;
}

etc.

mwarren
  • 759
  • 3
  • 6
0

So I've only done this once and I'm unsure whether the approach I did is the appropriate way.

But my approach was a method called typeConverter, which i would give an object as parameter, then you could take that parameter and look what object type it is and then create a new Person, with your value.

Although this approach could cause problems, when your class would have two integer fields. But I think you could find a solution for this, by giving it another parameter that defines, which field you'd want to convert it to.

I'm really sorry for my poor english, but I hope you get the principle.

TheYaINN
  • 114
  • 10
  • I understand your approach, but I was really looking for a way to cast the object directly, as in my question. – orezvani Jun 06 '19 at 09:20