記録のために、あなたの特定のケースは、継承よりも構成によって最もよく解決されると思います。accept
つまり、現在のようにサブクラス化するよりも、経由で取得したソケットをラップする方がよいでしょう。継承よりも構成を使用する場合について説明している優れた本 (Joshua Bloch による Effective Java) があります。それを読んだ後、継承がユースケースに適していると判断した場合は、以下に示すようにソケットに実装できます。
より特殊なソケットの実装:
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();
}
}
特殊なソケットを作成できるサーバー ソケットの実装:
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;
}
}
テストクラス:
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();
}
}
}