Franz Kafka
Franz Kafka

Reputation: 10831

Java set super instance of instance

I might just be unable to google for the right words, but I can't find an answer to the following question.

Is it possible to explicitly set the superclass of a new class instance. E.g. I have a SuperClazz instance and want to create a new instance of Clazz which extends SuperClazz. Can I just do something like this (the code is just what I want to do, it doesn't compile and is not correct):

    class Clazz extends SuperClazz{

Clazz(SuperClazz superInstance){
    this.super = superInstance;
}
}

Upvotes: 3

Views: 5303

Answers (4)

nort3x
nort3x

Reputation: 26

i cant claim that this will always work, you should always use copy-constructor as far as you can but in some cases (like you dont have access/right to change code or dont want to produce complexities) you can use this (example:),

import java.lang.reflect.Field;
import java.net.Socket;

public class SmarterSocket extends Socket {

    public SmarterSocket(Socket s) {
        super(); // default constructor for super instance

        // will iterate over public/private fields of "s" (superclass not included)
        for(Field f : s.getClass().getDeclaredFields()){
            try {
                f.setAccessible(true);
                f.set(this,f.get(s));
            }catch (Exception ignored){}
        }

    }

    public void doSmartStuff(){
        System.out.println("smarter");
    }
}

...

public static void main(String[] args){

        try {
            Socket s = new Socket();
            s.connect(new InetSocketAddress("stackoverflow.com",80));
            SmarterSocket ss = new SmarterSocket(s);
            ss.close();
            System.out.println("is SmartSocket closed: " + ss.isClosed());
            System.out.println("is Socket closed: " + s.isClosed());
            s.getOutputStream().write("hellow".getBytes()); // write to s
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

is SmartSocket closed: true
is Socket closed: false

java.io.IOException: Socket Closed
    at java.base/java.net.AbstractPlainSocketImpl.getOutputStream(AbstractPlainSocketImpl.java:489)
    at java.base/java.net.Socket$3.run(Socket.java:972)
    at java.base/java.net.Socket$3.run(Socket.java:970)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.net.Socket.getOutputStream(Socket.java:969)
    at Main.main(Main.java:47)

i used above example for hooking some monitors inside socket

but you have to be cautious:

1- reflection is complex: sometimes fields are being used for synchronization or more sophisticated stuff, you probably shouldn't update static (or more clearly static final) fields, you should have proper knowledge about internals of the class you are proxying it,and do some heavy tests to make sure everything is going smoothly

2- reflection is slow in runtime: test it, if it suit you let it be there

Upvotes: 0

AlexR
AlexR

Reputation: 115328

I think you have some missunderstanding in meaning or terms you are using.

Instance (or object) is what you create using new Clazz() at runtime. You cannot change it (unless you are using byte code modification tricks). What yo really want is to create 2 classes: base class and its subclass. Here is the simplest example.

class SuperClazz {
}

class Clazz extends SuperClazz {
}

If you want to call exlplitly constructor of super class from constructor of subclass use super(): class Clazz extends SuperClazz { public Clazz() { super(); } }

Upvotes: 1

JB Nizet
JB Nizet

Reputation: 691695

You're mixing inheritance and delegation. When an object calls

super.doThis();

it doesn't call doThis on another object which has the type of the object's superclass. It calls it on himself. this and super are the same thing. super just allows to access the version of a method defined in the superclass, and overridden in the subclass. So, changing the super instance doesn't make sense: there is no super instance.

Upvotes: 7

MaDa
MaDa

Reputation: 10762

The super class is always instantiated implicitly, so you cannot do it — "plant" the super class inside an extending class. What you probably want is a copy constructor.

Upvotes: 4

Related Questions