2009-03-15 5 views
3

그래서 두 개의 클래스가 있습니다. 하나는 추상적이다 :이 모든 클라이언트에 공통해야하기 때문에 자바 추상 ​​클래스 혼란 : 오버라이드 된 메소드가 호출되지 않음

public class BasicClient extends AbstractClient { 
    private IBasicServer basicServer; 

    public static void main(String[] args) { 
     new BasicClient(); 
    } 

    public BasicClient() { 
     try { 
      System.setSecurityManager(new RMISecurityManager()); 
      Registry registry = LocateRegistry.getRegistry(); 
      basicServer = (IBasicServer) registry.lookup(IBasicServer.LOOKUPNAME); 
      run(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    void displayOptions() { 
     BasicClientOptions.displayOptions(); 

    } 

    @Override 
    void processInputCommand(String input) { 
     // TODO Auto-generated method stub 

    } 
} 

지금 하위 클래스에서 나는 추상 클래스의 run() 메소드를 호출

public abstract class AbstractClient { 
    protected boolean running = true; 

    protected void run() { 
     Scanner scanner = new Scanner(System.in); 
     displayOptions(); 
     while (running) { 
      String input = null; 
      while (scanner.hasNext()) { 
       input = scanner.next(); 
      } 
      processInputCommand(input); 
     } 
    } 

    abstract void displayOptions(); 

    abstract void processInputCommand(String input); 

} 

하나는 구상 서브 클래스입니다. run() 메소드 내에서 abstract 메소드 displayOptions()를 호출합니다.

서브 클래 싱 된 displayOptions()를 재정의 했으므로 서브 클래 싱 된 메소드를 호출 할 것이라고 생각했지만 그렇지 않은 것 같습니다. 이 작업을 수행 할 수있는 방법이 있습니까? 아니면 내가 명백한 실수를했거나 추상 클래스가 어떻게 작동해야하는지 오해 했습니까?

P.S 나는 서브 클래 싱 된 displayOptions() 내에 print 문을 두어 보았습니다.이 메서드는 호출하는 메서드로 어떤 일을하지 않았는지 확인했습니다.

많은 감사,

답변

4

어쩌면 무언가가 당신의 BasicClientOptions.displayOptions() 전화에 문제가 있습니다

아담. BasicClient.displayOptions()이 호출되지 않는다는 것을 어떻게 아는지 궁금합니다.

다음은 간단한 버전입니다. 그것을 실행 해보십시오. 그것은 당신이 기대하는대로 행동합니다.

public abstract class BaseClass { 
    public void run() { foo(); } 
    public abstract void foo(); 
} 

public class Subclass extends BaseClass { 

    public static void main(String[] args) { new Subclass().run(); } 

    @Override 
    public void foo() { 
     System.out.println("I'm from the subclass"); 
    } 
} 
0

문제가 무엇인지 잘 모르는 경우 출력 내용을 인쇄 할 수 있습니까?

코드를 복사/붙여 넣기하고 두 행을 주석 처리하는 것 외에도 객체에 대한 적절한 소스를 가지고 있지 않습니다. 그것은 나에게 서브 클래스 메소드를 호출했다.

논리적으로 코드를 읽는 중 아무 것도 보이지 않는 것처럼 보였습니다.하지만 다른 문제가 없는지 확인하기 위해 내 눈으로 물건을 보는 것을 선호하므로 코드를 먼저 실행 해 보았습니다. :)

다음은 내가 수정 한 내용과 출력 내용입니다.

import java.util.Scanner; 

public abstract class AbstractClient { 
    protected boolean running = true; 

    protected void run() { 
    Scanner scanner = new Scanner("foo\\r\\nbar\\r\\n"); 
    displayOptions(); 
    while (running) { 
     String input = null; 
     while (scanner.hasNext()) { 
     input = scanner.next(); 
     } 
     processInputCommand(input); 
     running = false; 
    } 
    } 

    abstract void displayOptions(); 

    abstract void processInputCommand(String input); 

} 

import java.rmi.RMISecurityManager; 
import java.rmi.registry.LocateRegistry; 
import java.rmi.registry.Registry; 

public class BasicClient extends AbstractClient { 
    //private IBasicServer basicServer; 

    public static void main(String[] args) { 
    new BasicClient(); 
    } 

    public BasicClient() { 
    try { 
     System.setSecurityManager(new RMISecurityManager()); 
     Registry registry = LocateRegistry.getRegistry(); 
     //basicServer = (IBasicServer) registry.lookup(IBasicServer.LOOKUPNAME); 
     run(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    } 

    @Override 
    void displayOptions() { 
    //BasicClientOptions.displayOptions(); 
    System.out.println("We're in subclasses displayOptions()."); 
    } 

    @Override 
    void processInputCommand(String input) { 
    System.out.println("We're in subclasses processInputCommand()."); 
    } 
} 

내 출력

We're in subclasses displayOptions(). 
We're in subclasses processInputCommand(). 

그래서 효과가 클래스가 로깅 파까지되지 않았습니다 만 아마 일하는 것 같다.

희망이 도움이됩니다.

+0

내 자신의 게시물에 대한 의견, 나는 그 프로세스 스캐너를 그대로두고 프로세스 입력 쿼리를 차단하지 않도록 추가해야합니다. 즉, processInputCommand()는 제대로 호출되지 않습니다. 그래서 나는 스캐너를 \ fo \ r \ nbar \ r \ n 하드 코딩하여 borked했습니다. 데모 용으로 더 많은 기능을 제공합니다. 죄송합니다. –

2

클래스가 다른 패키지에있는 경우가 있습니까? 그렇다면 보호 된 것으로 대체 할 메소드를 선언해야합니다.

편집 : (당신이 다음 보호하는 방법 공개 /이 패키지의 외부 자녀 오버라이드 (override) 할 수 있습니다를 선언하면 설명이

:-) 도움이 될 것 같아요. 당신이 그것을 (패키지)/비공개로 만들 수 없다면. 프라이빗 메소드를 오버라이드 할 수는 없습니다. 어느 패키지 (패키지)도 같은 패키지 내의 클래스에 의해서만 오버라이드 (override) 할 수 있습니다.

키워드가 없으므로 (패키지)를 사용하므로 public/protected/private가없는 경우 (패키지) 액세스 권한을 얻습니다.

편집 :

(가) 위의 설명 주어진 가능성이 사실이 아니다 (클래스가 정말 추상적 인 것을 가정하고 @Override 주석을 사용했다).

실행 방법이 호출되고 있는지 100 % 확신합니까? System.out.println을 실행하고 호출되었는지 확인하십시오.

다른 예외를 포착하지 못하고 스택 추적 (또는 예외가 포착 된 것을 확인할 수있는 다른 방법)을 인쇄하지 못했습니다.

+0

TofuBeer - 네 말이 맞아. 사람들은 java의 기본 보호 기능에주의를 기울여야합니다! – Pat

0

이 스레드는 잠시 동안 조용 해졌으므로이 방법이 도움이 될지는 모르겠지만 다른 사람이 답변을 찾는 경우 게시 할 수 있다고 생각했습니다.

몇 분 전까지 만해도 인터페이스, 추상 클래스 및 구체적인 하위 클래스에서 비슷한 문제가 발생했습니다. 기본적으로 인터페이스는 10 개의 메소드를 정의하고, 추상 클래스는 그 중 2 개를 구현하고 나머지 8 개는 구체적인 클래스로 남겨 둡니다. 추상 클래스의 메소드 중 하나에 대한 구현은 구체적인 클래스에 의해 구현 될 수있는 메소드를 호출합니다.

모든 것이 잘 컴파일되었고 NetBeans는 런타임에 VM이 폭격하여 메서드 (구체적인 클래스에서 구현 된 메서드)가 존재하지 않는다고 말하면서 불평하지 않았습니다. 자바를 사용한 마지막 해부터 수년이 지났지 만,이 상황에서 예상되는 동작이 아니라는 것을 확신합니다 (누군가 틀렸다면 누군가 제발 저를 정정하십시오).

랩톱을 몇 시간 동안 차고 난 후에 추상 클래스를 호출하는 메서드의 추상 스텁을 추가하면 VM의 불만없이 구체적인 클래스로 전달할 수 있다는 것을 알게되었습니다. 이게 정상인가 아니면 그냥 운이 좋았나요?

어쨌든, 누군가 유용하다는 것을 알기를 바랍니다.

+0

정상이 아님. 뭔가 올바르게 컴파일되지 않은 것 같습니다. 런타임 중에 이전 버전의 인터페이스가 있다고 가정 해보십시오. 이 메서드를 추상 클래스에 추가하면 런타임에 이전 버전의 인터페이스가 있어도 문제가 해결됩니다. – Yishai

관련 문제