2010-07-08 4 views
6

Lo renderò il più breve e il più possibile, ma è una specie di problema complesso. Sto scrivendo in Java su una piattaforma Linux, per quello che vale.javac afferma che non sto sovrascrivendo un metodo in un'implementazione astratta della classe quando sono chiaramente

Versione breve dell'obiettivo: voglio avere una classe astratta denominata Client che funge da contenitore generico per le connessioni client. Client dovrebbe collegare ciascuna delle sue connessioni. Ho anche un codice semi-testato che riproduce la controparte del server in modo simile alla codifica. L'abstract Client dovrebbe essere implementato in qualcosa di più tangibile e istancabile. Nel mio caso, ho una classe chiamata FileClientGui che si estende Client e sovrascrive tutti i metodi astratti di Client con il metodo di base per ricevere i contenuti di un file dal server e visualizzarli. Ciò è ulteriormente complicato dal fatto che l'abstract Client è di per sé un'estensione di java.lang.Thread.

Quindi, ecco la mia struttura del file in termini generici:

/class/path/lib/client/Client.java

/class/path/com/fileclient/FileClientGui.java

Ci sono diverse altre classi personalizzate che entrambe queste file di riferimento, ma non sto ricevendo errori fuori di essi. Se ho bisogno di inserire il codice per questi articoli, fammelo sapere e li posterò.

Quindi eseguo questo lungo comando javac sul terminale che imposta il classpath e crea la directory e tutti i file rilevanti che devono essere compilati. L'unico errore che ricevo per niente di tutto questo codice è questo:

com/fileclient/FileClientGui.java:26: com.fileclient.FileClientGui is not abstract and does not override abstract method cleanClients() in lib.client.Client 

Il mio codice (vedi sotto) implementa chiaramente il metodo e tutti gli altri metodi astratti definiti in Client.java. Ho setacciato Internet e sembra che la maggior parte delle persone che riscontrano questo errore provi a fare qualcosa come implementare uno ActionListener e confondersi con tale implementazione, e molte volte, è solo un semplice problema di ortografia o di maiuscole. Ho passato il mio codice per assicurarmi che questo non sia un semplice problema "oops" del genere. Sospetto che in realtà sia una specie di collisione tra il nome della mia classe e il nome di qualche altra classe che in qualche modo finì nel mio classpath o nelle librerie/librerie native di Java, ma non riesco a trovare nulla di ovvio.

In ogni caso, ecco il mio codice.

Client.java:

package lib.client; 

import lib.clientservercore.Connection; 
import lib.simplefileaccess.Logger; 
import java.io.IOException; 
import java.net.Socket; 
import java.util.ArrayList; 
import java.lang.Thread; 

/** 
* 
* @author Ryan Jung 
*/ 
public abstract class Client extends Thread { 

    ArrayList<Connection> connections; 
    boolean isRunning; 
    Logger log; 

    public Client (String logFile) { 
     log = new Logger(logFile); 

     log.write("Initializing client..."); 

     connections = new ArrayList<Connection>(50); 

     log.write("Client initialized."); 
    } 

    public void logOut(String contents) { 
     log.write(contents); 
    } 

    public Logger getLogger() { 
     return this.log; 
    } 

    public ArrayList<Connection> getConnections() { 
     return connections; 
    } 

    public void addConnection(Connection c) { 
     connections.add(c); 
    } 

    public void removeConnection(Connection c) { 
     connections.remove(c); 
    } 

    public boolean getIsRunning() { 
     return isRunning; 
    } 

    public void setIsRunning(boolean r) { 
     isRunning = r; 
    } 

    public Connection connect(String host, int port) { 
     log.write("Creating new connection..."); 

     Socket s; 
     Connection c = null; 

     // Validate port 
     if (port <= 1024 || port > 65536) { 
      log.write("Invalid server port: " + port + ". Using 12321."); 
      port = 12321; 
     } 

     try { 
      s = new Socket(host, port); 
      c = connectClient(s); 
     } catch (IOException exIo) { 
      log.write("Could not connect to the server at " + host + ":" + port + ". Exception: " + exIo.getMessage()); 
      exIo.printStackTrace(); 
     } 

     log.write("Connected client to " + host + ":" + port); 

     return c; 
    } 

    @Override 
    public void run() { 
     log.write("Running client."); 
     runClient(); 
     log.write("Client finished running."); 
    } 

    abstract Connection connectClient(Socket sock); 

    abstract void runClient(); 

    abstract void cleanClients(); 

} 

FileClientGui.java:

package com.fileclient; 

import lib.client.Client; 
import lib.clientservercore.Connection; 
import lib.clientservercore.Connection.ConnectionStatus; 
import java.awt.BorderLayout; 
import java.awt.FlowLayout; 
import java.awt.event.ActionListener; 
import java.awt.event.ActionEvent; 
import java.io.IOException; 
import java.net.Socket; 
import java.net.UnknownHostException; 
import java.util.Iterator; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JTabbedPane; 
import javax.swing.JTextField; 
import java.lang.Thread; 

/** 
* 
* @author Ryan Jung 
*/ 
public class FileClientGui extends Client { 

    JFrame frmMain; 
    JPanel pnlMain; 
    JPanel pnlConnect; 
    JTabbedPane tabConnections; 
    JLabel lblHost; 
    JLabel lblPort; 
    JTextField txtHost; 
    JTextField txtPort; 
    JButton btnConnect; 

    public FileClientGui(String logFile) { 
     super(logFile); 

     logOut("Initializing client controller..."); 

     frmMain = new JFrame("Client"); 
     pnlMain = new JPanel(new BorderLayout()); 
     pnlConnect = new JPanel(new FlowLayout()); 
     tabConnections = new JTabbedPane(); 
     lblHost = new JLabel("Host:"); 
     lblPort = new JLabel("Port:"); 
     txtHost = new JTextField("localhost", 10); 
     txtPort = new JTextField("12321", 5); 
     btnConnect = new JButton("Connect"); 

     frmMain.setSize(450, 600); 
     frmMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frmMain.add(pnlMain); 
     pnlMain.add(pnlConnect, BorderLayout.NORTH); 
     pnlMain.add(tabConnections, BorderLayout.CENTER); 
     pnlConnect.add(lblHost); 
     pnlConnect.add(txtHost); 
     pnlConnect.add(lblPort); 
     pnlConnect.add(txtPort); 
     pnlConnect.add(btnConnect); 

     btnConnect.addActionListener(
      new ActionListener() { 
       public void actionPerformed(ActionEvent e) { 
        String host = txtHost.getText(); 
        int port = Integer.parseInt(txtPort.getText()); 
        try { 
         Socket sock = new Socket(host, port); 
         FileClientConnectionGui c = (FileClientConnectionGui)(connectClient(sock)); 
         tabConnections.addTab(c.getInetAddress().toString(), c.getMainPanel()); 
        } catch (UnknownHostException ex) { 
         logOut("Can't find host: " + host + ". Exception: " + ex.getMessage()); 
         ex.printStackTrace(); 
        } catch (IOException ex) { 
         logOut("Exception: " + ex.getMessage()); 
         ex.printStackTrace(); 
        } 
       } 
      } 
     ); 

     frmMain.setVisible(true); 

     logOut("Client controller initialized."); 

    } 

    public void removeConnection(FileClientConnectionGui c) { 
     logOut("Removing connection: " + c.getInetAddress().toString()); 
     tabConnections.remove(c.getMainPanel()); 
     logOut("Removed connection."); 
    } 

    Connection connectClient(Socket sock) { 
     logOut("Client controller is creating a new connection..."); 
     FileClientConnectionGui c = new FileClientConnectionGui(sock, getLogger(), this); 
     addConnection(c); 
     c.start(); 
     logOut("Client controller created a new connection."); 
     return c; 
    } 

    void runClient() { 
     setIsRunning(true); 
     logOut("Client controller is running."); 

     while (getIsRunning()) { 
      cleanClients(); 
      try { 
       sleep(500); 
      } catch (InterruptedException ex) { 
       logOut("Sleep interrupted. Exception: " + ex.getMessage()); 
       ex.printStackTrace(); 
      } 
     } 

     logOut("Client controller stopped running."); 
    } 

    void cleanClients() { 
     Iterator i = getConnections().iterator(); 
     try { 
      while (i.hasNext()) { 
       FileClientConnectionGui c = (FileClientConnectionGui)(i.next()); 
       if (c.getStatus() == ConnectionStatus.CLOSED) { 
        logOut("Removing dead client at " + c.getInetAddress().toString()); 
        tabConnections.remove(c.getMainPanel()); 
        removeConnection(c); 
       } 
      } 
     } catch (Exception ex) { 
      logOut("cleanClients Exception: " + ex.getMessage()); 
     } 
    } 

} 

mi prenderò tutto l'aiuto che posso ottenere, e vi ringrazio in anticipo per eventuali suggerimenti forniti. Sono completamente sconcertato da questo.

Forse ciò che più sconcerta di questo (e forse questo fornisce un indizio del problema?) È che posso commentare altre implementazioni di metodi astratti (ad esempio, runClient o connectClient), e non ottengo ulteriori problemi , proprio lo stesso.Inoltre, se aggiungo la direttiva @Override a uno di quegli altri in questo modo:

@Override 
Connection connectClient(Socket sock) { 
    logOut("Client controller is creating a new connection..."); 
    FileClientConnectionGui c = new FileClientConnectionGui(sock, getLogger(), this); 
    addConnection(c); 
    c.start(); 
    logOut("Client controller created a new connection."); 
    return c; 
} 

ottengo un errore aggiuntivo:

com/fileclient/FileClientGui.java:96: method does not override or implement a method from a supertype 

E chiaramente è override un metodo dal suo supertipo (che è cliente). Ho provato a sostituire "Client" con il classpath completo (lib.client.Client) e nessuno degli errori è stato modificato.

C'è qualcosa che mi manca? Qualcosa che non sto provando?

risposta

9

Credo che sia perché hai i metodi astratti a livello di pacchetto, che non sono visibili nella sottoclasse. Prova a renderli protetti invece.

Ecco un semplice paio di classi che riprodurre il problema:

package x1; 

public abstract class P1 
{ 
    abstract void foo(); 
} 

E poi:

package x2; 

public class P2 extends x1.P1 
{ 
    void foo() {} 
} 

loro compilazione dà:

P2.java:3: P2 is not abstract and does not override abstract method foo() in P1 
public class P2 extends x1.P1 
    ^
1 error 

Fare foo protetto in entrambe le classi correzioni il problema.

+0

Le classi non possono essere dichiarate protette, IIRC. Stai suggerendo che la classe astratta dichiari astratti i suoi metodi astratti? Proverò a farlo e fornirò i risultati. Grazie per la risposta rapida. – GradysGhost

+0

Bello! Grazie! In astratto Client.java, ho reso protette le definizioni delle funzioni astratte e, nell'implementazione FileClientGui.java, ho reso protette le implementazioni delle funzioni. Il codice compilato immediatamente senza errori. Ho eseguito il codice e ottenuto i risultati esatti che mi aspettavo. Grazie ancora. Questa è la risposta corretta. – GradysGhost