Declare a method to return this (java) - java

It is easy to define a method returning the same value as the argument:
class A {
public static void main(String[]args) {
Derived sth = new Derived();
String x = sth.foo("hello");
System.out.println(x);
Derived resultTypeIsKnown = sth.foo(sth); // <==== !!!
System.out.println(""+resultTypeIsKnown);
}
}
class Base {
<T>T foo(T t)
{
return t;
}
}
class Derived extends Base {
}
You see that the compiler knows that although foo() is declared in the Base class, the compiler knows that sth.foo(sth) returns an instance of the Derived class:
Derived derivedRatherThanBase = sth.foo(sth);
How do I declare that the return value is of the same class as the object whose method is called? (In particular, for a method that always returns this?)
Something like:
class Base {
<?ThisClass?> bar() {
return this;
}
}
I can write
<T>T getThis(T t)
{
return (T)this;
}
but x.getThis(x) uses an extra argument and produces a warning.
UPDATE OMG, what they are doing in the "possible duplicate"... But I already have the base class, it's a descendant of Collection. In other words, it is required that class Base extends Collection and knows its class.
And the real life code where I want to know THISCLASS already is very complex.
UPDATE2 As to the XY problem, what I want is:
class MyVerySpecialCollectionBase extends ... {
...
THISCLASS addAll(Collection items) { ... }
}
class MyExtendedVerySpecialCollection extends MyVerySpecialCollectionBase {
...
}
// use:
MyExtendedVerySpecialCollection x =
new MyExtendedVerySpecialCollection(aLotOfArgs)
.addAll(list1)
.addAll(list2);
The proposed solution sounds too complex and even less acceptable than either (1) redefining addAll() in each derived class or (2) making x.addAll(list1).addAll(list2); a separate statement.

Related

Return data type the same as class name via superclass?

I have an abstract class which has one abstract method. I want this method to return the same data type as the class which is overriding the method without having to cast the result of create or having to make a new method declaration on each subclass. I want it to all be declared seemlessly from the parent class.
I want the method to return a object whose data type is the same as the class it was called on.
EDIT: I removed print as people are getting confused with what I am asking
abstract class A
{
public abstract ... create();
}
class B extends A
{
#override
public ... create()
{
return new B...;
}
}
class C extends A
{
#override
public ... create()
{
return new C...;
}
}
Such that
B x1 = new B();
B x2 = x1.create();
// Since create was called on a B object
// a B object is returned, NOT AN "A" object
C y1 = new C();
C y2 = y1.create();
// create makes a C object this time,
// because it's called on a C object
// Problem: create() returns A object, even when
// called from class B or C.
// I want create() to return a B object if called from a B object.
What would be a good way of going about this? Thanks.
I no longer think this is the right answer. It's an answer, but is over-complicated. See my other answer.
There is no notion of a "self" type in Java's generics. The best you can do is to use self-bounded generics:
abstract class A<T extends A<T>>
{
public abstract T create();
}
Then, in your subclasses:
class B extends A<B>
{
#override
public B create()
{
return new B...;
}
}
Actually, there is an easier way to do it than with my other answer: just use a covariant return type in the subclass:
abstract class A {
public abstract A create();
}
class B extends A {
#Override public B create() {
return new B...
}
}
This is more pleasant if you are dealing with instances of A, since you don't have to make it generic (or, shudder, raw).
It also gives just as much of a guarantee that it returns a "self" type, i.e. no guarantee at all.
this.getClass() to get the class object, or, this.getClass().getSimpleName() to get a string of class name.
I have to question the design approach.
I'd be going for
abstract class A {
abstract Supplier<? extends A> create();
}
with
class B extends A {
public Supplier<B> create() {
return B::new;
}
}
(and C accordingly).
Then, there is
A b = new B();
A anotherB = b.create().get(); // will create a B
A c = new C();
A anotherC = c.create().get(); // will create a C
You don't need to make your create method abstract. If all the subclasses have a no-argument constructor, then you can just write this (in class A)
public A create() {
try {
return getClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
return null;
}
}
This checks the class of the object that you called the method on; and creates a new object of the same class, using its no-argument constructor.
Update
OP's comment suggests that they don't want to have to cast the returned value. If this is a requirement, then the casting can be avoided by changing the method signature as follows.
public <T extends A> T create() {
try {
return getClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
return null;
}
}

How to return the generic type of an object inside generic class?

I'd like to write a generic service that should work with an object of a specific type. When I write custom implementation of that service, I'd like to object to be variable. Therefore I wanted to override the method that creates that object.
But it won't work. Is it impossible in java to achieve the following?
class MyService<T extends Foo> {
//Type mismatch: cannot convert from Foo to T
public T createObject() {
return new Foo();
}
public void run() {
T t = createObject();
//work with the object
}
}
class Bar extends Foo;
class CustomService<Bar> {
#Override
public Bar createObject() {
return new Bar();
}
}
class NewArrayList extends ArrayList {
}
abstract class MyService<T> {
public abstract T createObject();
public void run() {
T t = createObject();
//work with the object
}
}
class CustomService extends MyService<NewArrayList> {
#Override
public NewArrayList createObject() {
return new NewArrayList();
}
}
The issue is that you are providing a default implementation which returns Foo. That implementation is not appropriate for subclasses and there is no way to force the subclass to override.
You should have MyService<T> and an abstract T createObject(). For Foo make a Foo-specific subclass FooService<Foo>.
Correct; you can't do that. Your T generic parameter stands for "some class which is a subclass of Foo" (where a class is a subclass of itself). You can't assume that it is Foo exactly, since it might be a class that extends Foo.
Think about it: if you had a class Bar extends Foo and you did:
MyService<Bar> service = ...
Bar myBar = createObject();
then your code would create a Foo and try to downcast it to a Bar — resulting in a ClassCastException. The whole point of generics is to avoid incorrect casts and their resulting exceptions.

Superclass static method returning 2 different subclasses

This is bad programming practice but I've been asked to do it as part of a larger assignment.
I am creating a superclass and then 2 subclasses. There is a static method in the superclass that should return either of the 2 subclasses depending on the result. How would I go about writing this method?
For example I need to do something like this
public abstract class Superclass{
public static subclass? createFromFilename(String fileName){
if(1==1)
return subclass1;
else
return subclass2;
}
}
Is this even possible?
I am not sure if this is what you are looking for, but if you want to return the class type, you can do that by writing the subclass name and appending a .class to get the class type. A proper return type would be the type Class with a generic limiting the result to Superclass and its subclasses.
public static Class<? extends Superclass> createFromFileName(String fileName) {
if (fileName.equals("A")) {
return SubclassA.class;
} else {
return SubclassB.class;
}
}
If, however, you want to return an object of the respective class, you can do that by simply return a new instance and set the return type to Superclass:
public static Superclass createFromFileName(String fileName) {
if (fileName.equals("A")) {
new SubclassA();
} else {
new SubclassB();
}
}
You can do it like this
public abstract superClass
{
public static superClass getBaseClass(...)
{
if(...)
{
return new baseClass1();//baseClass1 should derive from superClass
}
else
{
return new baseClass2();//baseClass2 should derive from superClass
}
}
}
You can now do this
superClass sc=superClass.getBaseClass(..);
if(sc instanceof baseClass1)
{
baseClass1 bc1=(baseClass1)sc;
//work with bc1...
}
if(sc instanceof baseClass2)
{
baseClass2 bc2=(baseClass2)sc;
//work with bc2...
}
You are trying to determine the return type as a result of the execution of the method. This is not possible to do. So you have to bear having the common superclass return type. BTW if you know at compile time the proper return type, why dont you change (having 2 methods?) the method to reflect that?

avoiding instanceof

I have a set of POJOs with a common superclass. Those are stored in a two-dimensional array of type superclass. Now, I want to obtain an object from the array and use methods of the subclass. This means I have to cast them to the subclass. Is there a way to do this without using instanceof?
Update: As a concrete example: http://obviam.net/index.php/the-mvc-pattern-tutorial-building-games/ See: "Add new actions (attack) when an enemy is clicked"
Yes - you can do it by inverting the flow: instead of your code doing something when the instance of the base class is of a specific type, pass an action item to the object, and let the object decide whether to perform it or not. This is the basic trick behind the Visitor Pattern.
interface DoSomething {
void act();
}
abstract class AbstractBaseClass {
abstract void performAction(DoSomething ds);
}
class FirstSubclass extends AbstractBaseClass {
public void performAction(DoSomething ds) {
ds.act();
}
}
class SecondSubclass extends AbstractBaseClass {
public void performAction(DoSomething ds) {
// Do nothing
}
}
AbstractBaseClass array[] = new AbstractBaseClass[] {
new FirstSubclass()
, new FirstSubclass()
, new SecondSubclass()
, new FirstSubclass()
, new SecondSubclass()
};
for (AbstractBaseClass b : array) {
b.performAction(new DoSomething() {
public void act() {
System.out.println("Hello, I'm here!");
}
});
}
If you know they're of the subclass type, then just cast them directly without an instanceof check.
But putting them in a superclass-typed array is telling the compiler to discard the information that they're actually of the subclass type. Either your superclass should expose those methods (perhaps as abstract), or your array should be of the subclass type (so you're not telling the compiler to forget the actual type of the objects), or you'll have to suck it up and do the cast (possibly with the instanceof test).
The only other notable alternative is that you might experiment with the visitor pattern, which passes an action to the object and lets the object decide what to do with it. That lets you override classes to ignore or perform the actions based on their runtime type.
You can try to use the Visitor design pattern.
http://en.wikipedia.org/wiki/Visitor_pattern
You have to ask yourself, why do you need to know their type, maybe this can be replaced with the use of an abstract method in the super class, that every one of them can implement according the desired result.
abstract class A{
abstract void visit();
}
class B extends A{
void visit() { print("B"); }
}
class C extends A {
void visit() { print("C"); }
}
I would avoid casting them in the first place.
Really think about what you're trying to do, and if they should be in the same collection like that.
If you have something like this
for(MyObj o : array) {
if(o instanceof A) {
((A)o).doA();
}
if(o instanceof B) {
((B)o).doB();
}
}
consider this instead
abstract class MyObj {
abstract void doIt();
}
class A {
void doIt() { doA(); }
}
class B {
void doIt() { doB(); }
}
Expose the method in the superclass, and then use overriding. Provide an empty implementation in the base class so that subclasses can ignore the action if needed.

Alternative to instanceof approach in this case

Hello I'm wondering what would be some more elegant alternatives to something like this:
class Base...
class A extends Base...
class B extends Base...
//iterator of colection containing mixed As and Bs i want to remowe Bs and do omething with As
while(iterator.hasNext()) {
Base next = iterator.next();
if(next instanceof A) // do something
if(next instanceof B)
iterator.remove();
}
Sow what are the alternatives...
Thank you for advices.
edit: Base class may have many subclasses not just two and their numbers may grow in time
You can create methods in Base and override them in A and B.
For example:
class Base{
public boolean shouldRemove(){
return false;
}
public void doSomething(){
}
}
class A extends Base{
#Override
public void doSomething() {
}
}
class B extends Base{
#Override
public boolean shouldRemove() {
return true;
}
}
and then you don't need know what class the object is an instance of:
while(iterator.hasNext()) {
Base next = iterator.next();
if(next.shouldRemove()){
iterator.remove();
}
else{
next.doSomething();
}
}
Do you really need to remove them from the list? Why don't you just have the method to do something in the Base class (doing nothing) and then just override it do to what you want on class A.
class Base{
public void doSomething(){
}
}
class A extends Base{
#Override
public void doSomething(){
// do something
}
}
Then you could just iterate over the list and calling the method doSomething on all objects.
for(Base base : list) {
base.doSomething();
}
This way only the classes that have overridden the doSomething() method will actually do something. All the other classes will just execute the dummy implementation in the Base class.
If Base was an abstract class you could declare the doSomething() as abstract and have the extending classes implement it. With this approach all classes would have to implement the method and classes for which you don't want any computation to be performed you would just provide a dummy implementation of that method. Alternatively you could even create an interface with the doSomething() method and have (which could even be a better decision) and have the Base class implement it, given that only the extending classes would actually implement the method.
instanceof is a good way to filter objects by type - and that's what you want to do. You have a mixed collection and so you need some kind of filter, either filter the input (store nothing but As) or filter the output (process nothing but As).
If you just don't like "instanceof", you could use an enum to specify the type and add a final method to get the type at Base:
enum Type { ATYPE, BTYPE };
public Base {
final private Type type;
public Base(Type type) { this.type = type; }
public Type getType() { return type; }
// ...
}
public A {
public A() { super(Type.ATYPE); }
}
while(iterator.hasNext()) {
Base next = iterator.next();
switch (next.getType) {
case ATYPE: // do something and break
case BTYPE: iterator.remove(next); break;
}
}
i think is very short and clear solution and has no alternatives (without code growing),
just add else if instead of if in second case
Also you can split code on function calls, and if statement will not be huge
Another solution is to create Map of delegates that will be called. Like this:
interface ISimpleDelegate{ void doSomeLogic(Base b) }
`Map delegates = new HashMap();
After this add your logic as anonymous classes that realizes ISimpleDelegate.
delegates.put(A.class, new ISimpleDelegate() { //write your logic here });
I hope that the idea is clear
And in your loop you just call delegates:
while(iterator.hasNext()) {
Base next = iterator.next();
delegates.get(next.getClass()).doSomeLogic(next);
}
In general, a nice solution to avoid instanceof is to use the so-called visitor pattern.
For this pattern, you need an additional interface (the Visitor), an implementation of it that contains the code you want to execute and an additional method in all classes of your hierarchy, so this might be overkill in small cases (but it is very handy if there is not only A and B, but more types).
In your case it would look like this:
interface Visitor {
void visit(A a);
void visit(B b);
}
class Base {
abstract accept(Visitor v);
}
class A extends Base {
accept(Visitor v) {
v.visit(this);
}
}
class B extends Base {
accept(Visitor v) {
v.visit(this);
}
}
class MyVisitor implements Visitor {
visit(A a) {
doSomethingWithA(a);
}
visit(B b) {
doSomethingWithB(b);
}
}
It is used like this:
MyVisitor v = new MyVisitor();
while(iterator.hasNext()) {
Base next = iterator.next();
next.accept(v);
}
An advantage is that you have to write most of the code only once. If you want to do other things with A and B in another place of your program, just write another implementation of Visitor. You don't need to modify Base, A and B as you would if you'd add doSomething() to these classes.
Edit:
If the number of sub-classes increases, you need to change all your existing implementations of Visitor. However, at least the compiler tells you about that. With instanceof you might end up forgetting a place where you need to add a handling clause. This can at most be detected at runtime, whereas the visitor pattern gives you compile-time safety.

Categories