0

I've written a class which extends Socket class - with the intention of retaining all the methods from a regular socket, while adding two methods of my own:

public class ClientSocket extends Socket{

private long lastOnline;

public ClientSocket() {
      super();
}

public long getLastOnline() {
    return lastOnline;
}

public void setLastOnline(long lastOnline) {
    this.lastOnline = lastOnline;
}

When I'm trying to initialize a new instance of this class, and to add an open socket to it, I'm doing something wrong (or maybe something is wrong with me ), and it tells me that I cannot set a socket to ClientSocket object (although it extends Socket):

ClientSocket socket = serverSocket.accept();

How can I resolve this? Thanks!

1
  • BTW, it's called inheritance. Commented May 13, 2012 at 12:45

3 Answers 3

7

serverSocket.accept() returns an ordinary Socket, not a ClientSocket.
A ClientSocket is a Socket, but not vice-versa.

Sign up to request clarification or add additional context in comments.

3 Comments

so there is basicly no way to do it throw inherition, i should built instead a simple class with the extra function ad variable named socket inside which contains my Socket object
Correct. You cannot use inheritance to modify an object created by someone else.
@AsafNevo - its actually possible to return your own socket implementation from a server socket, but it requires some extra work which I think in your case is unnecessary. Composition is more appropriate to your use case than inheritance.
1

You could use composition:

public class ClientSocket {

    private final Socket socket;
    private long lastOnline;

    public ClientSocket(Socket socket) {
        this.socket = socket;
    }

    public long getLastOnline() {
         return lastOnline;
    }

    public void setLastOnline(long lastOnline) {
        this.lastOnline = lastOnline;
    }

    ...
}

then to create a ClientSocket:

ClientSocket clientSocket = new ClientSocket(serverSocket.accept());

Comments

0

For the record, I believe your particular case is best solved by composition over inheritance. Aka, its better for you to wrap the sockets retrieved via accept, rather than trying to subclass as you are now. There is a good book (Effective Java by Joshua Bloch), that describes when to use composition over inheritance. After reading it, if you decide that inheritance is appropriate for your use case, you could implement it for sockets as shown below:

A more specialized socket implementation:

public class AuditableClientSocket extends Socket {
   private long lastPacketReceived = -1;

   // Constructors removed for brevity. Add them back here

   public long getLastPacketReceived() {
      return lastPacketReceived;
   }

   protected void setLastPacketReceived(long lastPacketReceived) {
      this.lastPacketReceived = lastPacketReceived;
   }

   public String formatLastReceived() {
      if (lastPacketReceived < 0)
         return "Never";

      return new Date(lastPacketReceived).toString();
   }
}

A server socket implementation capable of creating the specialized sockets:

public class AuditableClientServerSocket extends ServerSocket {

   // Constructors removed for brevity. Add them back here

   @Override
   public Socket accept() throws IOException {
      if (isClosed())
         throw new SocketException("Socket is closed");
      if (!isBound())
         throw new SocketException("Socket is not bound yet");
      final Socket s = new AuditableClientSocket((SocketImpl) null);
      implAccept(s);
      return s;
   }
}

Test classes:

public class AuditableClientServer implements Runnable {
   public static void main(String[] args) {
      AuditableClientServer server = new AuditableClientServer();
      new Thread(server).start();
   }

   private AuditableClientServerSocket serverSocket = null;

   public void run() {

      try {
         serverSocket = new AuditableClientServerSocket(5656);
         final AuditableClientSocket sock = (AuditableClientSocket) serverSocket.accept();
         System.out.printf(
               "Client connected at %s. Last received packet at %s",
               new Date(), sock.formatLastReceived());

         sock.close();
         serverSocket.close();
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
}

public class AuditableClient {
   public static void main(String[] args) {
      try {
         Socket s = new Socket("localhost", 5656);
         s.close();
      } catch(IOException ioe) {
         ioe.printStackTrace();
      }
   }
}

4 Comments

Good snippet. Could you give more details... You write final Socket s = new AuditableClientSocket((SocketImpl) null); but AuditableClientSocket constructor is skipped. What constructor is supposed to be?
I excluded the constructors for the sake of brevity. Basically you want to add constructors matching all the ones from Socket. For reference, the snippets in my answer reference the Socket(SocketImpl impl) constructor.
Thank you for comment. But isn't the Socket(SocketImpl impl) has protected modifier docs.oracle.com/javase/1.4.2/docs/api/java/net/…? How to walk it around?
... I watched the example as download.java.net/jdk8/docs/technotes/guides/net/… but it doesn't show the "install system-default SocketImpl" code. So I am not pretty sure what "install system-default SocketImpl" exactly means. Could you comment please?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.