using equals or instanceof in toString - java

Ok guys I have a program with a 'MartianManager' class: *Note code is not complete still have some missing pieces just supplied entire code for reference of somewhat how it is going to look when complete
import java.util.ArrayList;
public class MartianManager {
private ArrayList<Martian> martians;
private ArrayList<Martian> teleporters;
public void addMartian(Martian m) {
martians.add(m);
if(m instanceof GreenMartian)
teleporters.add(m);
}
//public Object clone() {
public Martian getMartianClosestToID(int id) {
}
public void groupSpeak() {
for(Martian m : martians) {
m.speak();
}
}
public void groupTeleport(String dest) {
}
}
and Martian class:
public abstract class Martian implements Cloneable {
int id;
public Martian(int id) {
this.id = id;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public int getId() {
return id;
}
public boolean equals(Object o){
return this.getId() == ((Martian)o).getId();
}
public abstract void speak();
public String toString(){
String str = "";
if (this instanceof GreenMartian) {
str = "Green martian" + id;
}
if (this instanceof RedMartian) {
str = "Red martian" + id;
}
return str;
}
}
it is extended with GreenMartian:
public class GreenMartian extends Martian implements ITeleport{
public GreenMartian(int id) {
super(id);
}
public void speak() {
System.out.println(id + "Grobldy Grock");
}
public void teleport(String dest) {
System.out.println(id + "teleporting to " + dest);
}
}
also extended with RedMartian:
public class RedMartian extends Martian {
public RedMartian(int id) {
super(id);
}
public void speak() {
System.out.println(id + "Rubldy Rock");
}
}
I actually have a few questions , but for now my question is in the toString of the Martian class. It should return a string like this: "Red [or Green] martian" +id. I need to determine the type of Martian, I started to use the instanceof but like this "Martian couldn't be resolved to a variable". I'm trying to determine if this would be the best way or if an equals() would be the best way to determine the type?
Also this is my first time using "clone" so not sure how it works exactly, but had a thought is there a way to determine what the "clone" was and determine it that way?
Thanks for any and all help!

No
public String toString(){
String str;
if (Martian instanceof GreenMartian) {
}
in abstract Martian class is a bad idea. You don't want your parent class to depend on its children.
Implement a toString() method in each subclass instead and let polymorphism do its work.
If you absolutely have to
if (Martian instanceof GreenMartian) {
is wrong. You use instanceof as so
instanceOfClass instanceof SomeClass
In this case you get a reference to instanceOfClass with the this keyword, since you are calling the method on an instance
this instanceof GreenMartian

You really should not have a parent class reference any classes that extend it. This is bad practice (and might not actually work, i haven't tested). You should really just override the toString function in each extended class.
public class GreenMartian extends Martian implements ITeleport{
public GreenMartian(int id) {
super(id);
}
public void speak() {
System.out.println(id + "Grobldy Grock");
}
public void teleport(String dest) {
System.out.println(id + "teleporting to " + dest);
}
#Override
public String toString() {
return "GreenMartian: whatever info you'd like to include.";
}
}
Now, if you want to have a similar format for all subclasses, you have two options. One is to call the toString method of the parent class, and prepend that to the subclass's toString method.
#Override
public String toString() {
return super.toString() + "GreenMartin: info.....";
}
//The parent toString could look like this:
#Override
public String toString(){
return "Martian( ... put any parent class info here, id ect)";
}
The final output for a GreenMartian toString call then may look like this:
Martian(id:23) GreenMartian(planet:greenburg)
A Third option would be to have a common string format in the parent class. For example, in the parent class, include this attribute:
protected static final String format = "Class: %s, id: %s, info: %s";
Then, in the subclass toString, you can do this:
#Override
public String toString() {
return String.format(format,this.getClass().toString(),id,myInfo);
}

You can use String name = this.getClass().getSimpleName() to get the name of your class. Then you can check name.substring(0,1).equals("G") or name.substring(0,1).equals("R") to detect Red or Green.

FWIW, it should be if (this instanceof GreenMartian) - but IMHO whenever you are tempted to use such an downcast (upcast??), it is an sign of bad OO design. Rather write a specialized toString()method for your martians. And you should really check for o==null in your equals() method.

Martian is not a variable. Try this instead:
if(this instanceof GreenMartian)

Related

How Cast to unknow class

I have a class:
public class Example {
public String name;
}
but this class does not have to be called Example may be different(like Example2, AnotherExample I don't know how), the problem is that I do not know how to be called.
In another class I have a method which take as parameter a list of objects.
My Example class:
public class ObjectClass{
public List<Object> doSomething(List<Object> objects) {
for(int i = 0 ; i < objects.size();i++) {
Class<?> c = objects.get(i).getClass();
System.out.println("class name " + c.getCanonicalName());// i get name my class
System.out.println(((Example) objects.get(i)).name);
}
}
}
When I change the cast Example to another class like this System.out.println(((c) objects.get(i)).name);
it doesn't work.
My class can call itself differently then cast to Example will not work.
Generally speaking I want get value of name, while not knowing how the class is named. But I select which class with a field name(or by having an annotation).
Edit: is one problem, it is my homework and i can't change class Example, and i can't change method doSomething.
If you look specifically after a field name, you can also iterate over all fields via reflection and access the right one.
public List<Object> doSomething(List<Object> objects) {
for (int i = 0; i < objects.size(); i++) {
Class<?> c = objects.get(i).getClass();
for (Field field : c.getFields()) {
if ("name".equals(field.getName())) {
try {
System.out.println("class name " + c.getCanonicalName());// i get name my class
System.out.println(field.get(objects.get(i)));
} catch (Exception e) {
}
}
}
}
return null;
}
Welcome to the wonderful world of polymorphism. Here is what you can do:
interface Named
{
String getName();
}
public class Example implements Named
{
public String name;
#Override
public String getName()
{
return name;
}
}
public class AnotherExample implements Named
{
public String name;
#Override
public String getName()
{
return name;
}
}
then you can do this:
System.out.println(((Named) objects.get(i)).getName());
then of course I would also recommend that you do the following:
public List<Named> doSomething(List<Named> objects) {
so that then you can do this:
System.out.println(objects.get(i).getName());
Edit after clarification:
If you cannot add your own interface, then try something like this:
Object foo = objects.get(i);
if( foo instanceof Example )
{
Example example = (Example)foo;
...do something with example...
}
else if( foo instanceof AnotherExample )
{
AnotherExample anotherExample = (AnotherExample)foo;
...do something with anotherExample...
}
else
{
assert false; //I do not know what class this is.
}

how to see the class name containing the actual code

package a;
public class A {
public String toString() {
// return "I am an a.A"; is too primitive ;)
return "I am an " + getClass().getName(); // should give "a.A"
}
}
--
package a;
public class X extends A {
public static void main(String[] args) {
X test = new X();
System.out.println(test); // returns "I am an a.X"
}
}
I also tried with this.getClass() and super.getClass(). How can I get the class name of where toString() and getClass() is coded actually ? (a.A)
This is just a simplified sample, my point is how to avoid hard coding the base class name in the first file (A.java)
package a;
public class A {
public String toString() {
return "I am an " + A.class.getName();
}
}
should do the trick.
Change :
getClass().getName()
into
A.class.getName()
just iterate over all super
public String toString() {
Class cl = getClass();
while (cl.getSuperclass() != Object.class)
cl = cl.getSuperclass();
return cl.getName();
}

How can I refer to the type of the current class?

This is kind of difficult to explain, but I've looked everywhere, and I couldn't find any good answer.
I've also seen Stack Overflow questions How can I refer to the class type a interface is implementing in Java? and How do I return an instance of an object of the same type as the class passed in using Java 6?, but they couldn't answer my question. There is an exception when I apply inheritance.
There is an example, to make it easier to understand:
Let's say I have some interface called SelfMaker:
public interface SelfMaker <SELF>{
public SELF getSelf();
}
And A have a Dog, which can procreate with another dogs. So the dog is a "SelfMaker", like this:
public class Dog implements SelfMaker<Dog> {
String color;
public String toString() {
return "some " + color + " dog";
}
public Dog procreate(Dog anotherDog) {
Dog son = getSelf();
son.color = color;
return son;
}
#Override
public Dog getSelf() {
return new Dog();
}
}
But then, I have a DomesticDog, who is a Dog, but it has a lovely family who named him. Like this:
public class DomesticDog extends Dog {
private String name;
public String toString() {
return super.toString() + " named " + name;
}
}
Now, I have some class that handles couples of things that are "SelfMaker"s, let's call this class "Couple". Like this:
public class Couple<T extends SelfMaker<T>> {
private T first;
private T second;
public String toString() {
return first.toString() + " and " + second.toString();
}
}
THE EXCEPTION:
The exception comes when I want to create a couple of DomesticDogs. Like this:
public class CoupleOfDomesticDogs extends Couple<DomesticDog>{
public DomesticDog procreate(){
DomesticDog son = first.procreate(second);
return son;
}
}
This will throw an exception on <DomesticDog> complaining: Bound mismatch: The type DomesticDog is not a valid substitute for the bounded parameter <T extends SelfMaker<T>> of the type Couple<T>
I have already tried to change the generalised variable from class Couple to this: Couple<T extends SelfMaker<?>> but the "son" won't be a DomesticDog (and I want the "son" to be a DomesticDog). If I add some cast, then it will compile, but it will be less legible.
So... here is the question: Is there a way to achieve this without castings and generalizations?
There is no way that I can think of to do this without casting. Your problem will be solved if you override the procreate and getSelf methods of DomesticDog and change the declaration of class Couple as such:
public class DomesticDog extends Dog {
private String name;
public DomesticDog procreate(Dog anotherDog) {
return (DomesticDog)super.procreate(anotherDog);
}
public Dog getSelf() {
return new DomesticDog();
}
public String toString() {
return super.toString() + " named " + name;
}
}
public class Couple<T extends SelfMaker<? super T>> {
protected T first;
protected T second;
public String toString() {
return first.toString() + " and " + second.toString();
}
}
If you don't want to override getSelf() in every subclass of Dog, you could make the following change in class Dog:
public Dog getSelf() {
Class<? extends Dog> thisClass = this.getClass();
try {
return thisClass.newInstance();
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
}
throw new UnsupportedOperationException(thisClass
+ " does not supply a public no-arg constructor");
}
This guarantees that every value returned by getSelf() is an instance of this.getClass(). But you would still have to cast the return value of procreate() for subclasses. There is no way to explicitly specify a return type as this.getClass().
You will have to make Dog generic and abstract, with a type parameter that indicates the result of getSelf(). Each type of Dog will then need to implement this with themselves as the parameter:
public abstract class Dog<T> implements SelfMaker<T> {
String color;
public String toString() {
return "some " + color + " dog";
}
public T procreate(T anotherDog) {
T son = getSelf();
son.color = color;
return son;
}
}
public class DomesticDog extends Dog<DomesticDog> {
private String name;
public String toString() {
return super.toString() + " named " + name;
}
#Override
public DomesticDog getSelf() {
return new DomesticDog();
}
}

How would I overload method in an interface?

if I have this interface
public interface someInterface {
// method 1
public String getValue(String arg1);
// method 2
public String getValue(String arg1, String arg2);
}
I want to be able to pass in 1 or 2 string to the getValue method without having to override both in each implementing class.
public class SomeClass1 impelments someInterface
{
#Override
public String getValue(String arg1);
}
public class SomeClass2 implements someInterface
{
#Override
public String getValue(String arg1, String arg2);
}
this won't work because SomeClass1 needs to implement method 2 and SomeClass2 needs to implement method 1.
Am I stuck doing this?
public interface someInterface2 {
public String getValue(String... args);
}
public class SomeClass3 implements someInterface2
{
#Override
public String getValue(String... args) {
if (args.length != 1) {
throw IllegalArgumentException();
}
// code
}
}
public class SomeClass4 implements someInterface2
{
#Override
public String getValue(String... args) {
if (args.length != 2) {
throw IllegalArgumentException();
}
// code
}
}
someInterface2 someClass3 = new SomeClass3();
someInterface2 someClass4 = new SomeClass4();
String test1 = someClass3.getValue("String 1");
String test2 = someClass4.getValue("String 1, "String 2");
Is there a better way of doing this?
An interface serves as a contract for the users of that interface: you specify what methods are available (in all implementations) and how they are called. If two implementations of an interface need a different method, then that method should not be part of the interface:
public interface Lookup {
}
public class MapLookup implements Lookup {
public String getValue(String key) {
//...
}
}
public class GuavaLookup implements Lookup {
public String getValue(String row, String column) {
// ...
}
}
In your program, you will know which implementation you use, so you can simply call the right function:
public class Program {
private Lookup lookup = new MapLookup();
public void printLookup(String key) {
// I hardcoded lookup to be of type MapLookup, so I can cast:
System.out.println(((MapLookup)lookup).getValue(key));
}
}
Alternative approach
If your class Program is more generic and uses dependency injections, you may not know which implementation you have. Then, I would make a new interface Key, which can be either type of key:
public interface Lookup {
// ...
public String getValue(Key key);
}
public interface Key {
}
public MapKey implements Key {
private String key;
// ...
}
public GuavaKey implements Key {
private String row, column;
// ...
}
The dependency injection in your program might come from some factory implementation. Since you cannot know which type of lookup you use, you need a single contract for getValue.
public interface Factory {
public Lookup getLookup();
public Key getKey();
}
public class Program {
private Lookup lookup;
public Program(Factory factory) {
lookup = factory.getLookup();
}
public void printLookup(Factory factory) {
System.out.println((lookup.getValue(factory.getKey()));
}
}
As of Java 8, you can have an interface provide an implementation of a method, through the use of the default keyword. Therefore a new solution would be to provide a default implementation of both methods which maybe throws an exception, then derive the actual implementation from the default interface.
Anyways here is how you can do this:
public interface SomeInterface {
// method 1
default String getValue(String arg1) {
// you decide what happens with this default implementation
}
// method 2
default String getValue(String arg1, String arg2) {
// you decide what happens with this default implementation
}
}
Finally, make the classes override the correct methods
public class SomeClass1 implements SomeInterface {
#Override
public String getValue(String arg1) {
return arg1;
}
}
public class SomeClass2 implements SomeInterface {
#Override
public String getValue(String arg1, String arg2) {
return arg1 + " " + arg2;
}
}
A solution (not very elegant) might look loke this:
public abstract class SomeClass {
public String getValue(String arg1) {
throw new IllegalArgumentException();
}
public String getValue(String arg1, String arg2) {
throw new IllegalArgumentException();
}
}
public class SomeClass1 extends SomeClass {
public String getValue(String arg1) {
// return sth
}
}
public class SomeClass2 extends SomeClass {
public String getValue(String arg1, String arg2) {
// return sth
}
}
However there's a drawback - SomeClass1 and SomeClass2 can't inherit directly other class.
If the second value can be considered optional in a sense and you always have the 2 arguments when calling you could create a wrapper class which implements the 2 parameter interface passing the 1 parameter implementation as a constructor parameter and calling that in the method, e.g. something like this:
interface A{
method1(P1)
}
interface B{
method2(P1, P2)
}
class Wrap implements B{
Wrap(A impl)
override method2(P1, P2){
call impl.method1(P1)
}
}
public interface SomeInterface {
default void print(String s) {
System.out.println(s);
}
}
public class SomeClass implements SomeInterface {
/**
* Note the this overloads {#link SomeInterface#print(String)},
* not overrides it!
*/
public void print(int i) {
System.out.println(i);
}
}

Factory class design issue in java

I have two classes
public class PrepaidPackage {
private String name;
private String serviceClassID;
private boolean isTranferable;
public boolean isTranferable() {
return isTranferable;
}
public void setTranferable(boolean isTranferable) {
this.isTranferable = isTranferable;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getServiceClassID() {
return serviceClassID;
}
public void setServiceClassID(String serviceClassID) {
this.serviceClassID = serviceClassID;
}
}
other class is
public class PostpaidPackage {
private String name;
private boolean isTranferable;
public boolean isTranferable() {
return isTranferable;
}
public void setTranferable(boolean isTranferable) {
this.isTranferable = isTranferable;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I want to create a factory class which on base of package type create relevant class. But if you look at above clasess they dont have same type of methods and variables. So please guide how create interface or abstract class for above class?
Now factory will return class name Package. Would i able to call methods which are not present in other class.
Updates
Please suggest if i break my package into two classes like
public abstract class MyPackage {
public abstract PackageSpec getSpec();
public abstract PackagePrepaidDetails getDetail();
}
Now common attributes will be in PackageSpec and prepaid stuff in packageDetails.
Its kind of abstract factory pattern.
public class PrepaidPackage extends MyPackage{
PackageSpec spec;
public Spec getSpec() {
spec = new PackageSpec();
spec.setTranferable(true)
spec.setName("abc");
return spec;
}
public PackagePrepaidDetails getDetails() {
details = new PackagePrepaidDetails ();
details.setServiceClassID(123)
return details;
}
}
public class PostpaidPackage extends MyPackage{
PackageSpec spec;
public Spec getSpec() {
spec = new PackageSpec();
spec.setTranferable(true)
spec.setName("abc");
return spec;
}
}
I recomment you to have an interface if you don't have already. You do not neccessarily need it, but it is a good practice if they are so similar:
public interface Package {
public boolean isTranferable();
public void setTranferable(boolean isTranferable);
public String getName();
public void setName(String name);
}
Then in your calling code, you have a Package from your factory and:
Package p = myFactory.nextPackage(); // or something
if (p instanceof PrepaidPackage) {
PrepaidPackage prepaid = (PrefpaidPackage)p;
// and do the thing you want
} else if (p instanceof PostpaidPackage) {
PostpaidPackage postpaid = (PostpaidPackage)p;
// amd do the other things
}
Thing you are recommended to llok into is the instanceof operator and type casting.
A quick fix, not an ideal one is to have an interface that represents all the methods in the Prepaid class and leave them unimplemented in the Postpaid. That will solve the problem in the short term. I would suggest that you have a relook of the classes and the usages to avoid unimplemented methods in the code.
Well for an abstract super class you have to group everything common to both :
public abstract class MyPackage { // not sure you can call a class just "Package"
private String name;
private boolean isTranferable;
public boolean isTranferable() {
return isTranferable;
}
public void setTranferable(boolean isTranferable) {
this.isTranferable = isTranferable;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
then both inherits from it (the first adds serviceClassID and the second nothing)
your factory function will return a MyPackage (or AbstractPackage, whatever), but to access the specific function you'll have to cast after an instanceof test.
Two possible design choices you can make:
Have the prepaid package extend
postpaid package and your factory
then returns objects of type
postpaid package, the code which
calls the factory is then
responsible for inspecting the type.
Have a package interface which
defines all of the methods and have
postpaid package define the methods
to throw an
UnsupportedOperationException (ala
the way collections defines some
operations as optional.) or return
some kind of sentinel value (i.e. null)
For either of the above you could add another method getType() which returns an enum of the various package types you wish to implement, and this could then be used in the code that accesses the factory objects to determine which methods are available.

Categories

Resources