2011-04-13 4 views
2

다음 시나리오가 있습니다. 인터페이스 A, 100 클래스 B0 ... B99, A0 및 B0, B2 ...를 확장하는 C0, C2 ... C98 클래스 만 구현하는 B99 B98.Java 상속 문제 : vtable을 넘어서

B 클래스는 MySQL 데이터베이스에서 작동하며 테이블에서 다양한 작업을 수행합니다. C 클래스는 B 클래스 (유효성 검사, 권한 등)에 추가 논리를 추가합니다. B 클래스는 도구에 의해 생성되는 반면 C 클래스는 코더에 의해 작성됩니다.

클라이언트 응용 프로그램은 B 클래스를 사용하며 C 클래스에 액세스 할 수 없습니다. 메서드가 B 개체에 대해 호출되면 클라이언트는 개체를 serialize하여 호출 할 메서드 이름과 함께 서버 응용 프로그램으로 보냅니다.

서버는 B 개체를 받고이를 A로 캐스팅합니다. 그러나 서버는 해당 클래스가 있으면 C 클래스에서 재정의 된 메서드를 실행하고 그렇지 않으면 B 메서드를 실행하려고합니다. 정상적인 동작은 B의 메서드 만 실행합니다.

받은 개체를 C로 캐스트하는 거대한 SWITCH 문을 사용하지 않으면 서버에서 어떻게 처리 할 수 ​​있습니까?

편집 : 나는 자바를 처음 접했고 반사가 무엇을 할 수 있는지 알지 못했다. 구글 (thisthis)에서 약간의 도움으로 내 문제를 해결했습니다. 내가 원하는 것을 위해 동적 캐스팅을 사용할 수 있습니다. 모두에게 감사드립니다.

+0

는 건가요가 매핑을 발견하거나 호출하는 경우 같은 B 객체를 반환하는 공장에 전달 클라이언트 'B b = new B();'를 할 것이지만, 응용 프로그램이 어떻게해서'b'를'C'로 변환하기를 원합니까? –

+0

실제로. 서버는 객체를 A obj = Receive()로 받고 메소드를 obj.someMethod()로 호출합니다. 서버가 호출 할 메소드를 결정하는 방법은 중요하지 않습니다 (모든 클래스에서 구현되는 메소드가 몇 개 있습니다). 나는 C가 사용 가능하다면 C의 someMethod()가 호출되기를 바란다. – Rimio

답변

1

당신은 런타임 타입 B의 객체를 가지고 있고 그것을 마치 C 타입의 객체 인 것처럼 호출하려고합니다. 이것은 상속이 어떻게 작동 하는지를 나타내는 것은 아닙니다. 일반적으로 C의 모든 필드를 가지고 있지 않기 때문에 원래 C로 작성되지 않은 한 C로 다운 캐스트 할 수 없습니다.

C 클래스는 B에 추가 필드를 추가하지 않는다고 추측합니다 (if 그들은 당신의 질문을 이해하지 못할 것입니다). 그들은 추가 필드를 추가하지 않기 때문에 C로 처리하는 것이 얼마나 의미가 있는지 알 수 있지만 실제로 그것을 수행하는 좋은 방법은 없습니다. 나는 말할 것입니다 :

  1. 처음에는 왜 Bs와 Cs가 있습니까? 왜 B 급, 모든 특권 등을 가지고 그것을 사용하지 않는가?
  2. 그렇지 않으면 반사를 사용할 수 있다고 생각합니다. B 클래스 객체 중 하나를 사용하고 새로운 해당 C 객체를 생성하고 모든 필드를 복사하는 일반 코드를 작성합니다.
+0

B 클래스는 도구로 생성됩니다. 추가 코드를 작성하고 도구를 다시 실행하면 작업이 중단됩니다. – Rimio

+1

재생성시 기존 클래스를 덮어 쓰지 않고 병합하는 워크 플로를 사용할 수 있습니다. 클래스에서 코드를 배치하는 방법을 신중하게 고려하면 병합은 쉽지 않습니다. 이렇게하면 코드가 보존되지만 자동 생성 된 새 항목을 추가 할 수 있습니다. –

+0

네,하지만 이것은 또한 정말로하고 싶지 않은 클라이언트에게 로직을 노출시킬 것입니다. 예를 들어 권한은 서버 측에서 검사됩니다. 코드는 컴파일되지 않습니다. – Rimio

2

그런 접근 방식은 나에게 정말 이상하게 들립니다. 명령 (예 : 명령 이름을 정의하는 문자열)을 제공하고 해당 명령에 대한 명령 개체를 등록하는 것이 어떨까요? 그런 다음 직렬화 된 매개 변수와 함께 명령을 전송하면됩니다.

편집 :는 C 객체는 실제로 B 객체에 장식 될 경우 귀하의 설명에서

것 같습니다. 이 경우 해당 B를 상속받지는 않지만 해당 B를 참조하면 서버는 전달 된 B (예 : 클래스 또는 다른 식별자를 기반으로)의 데코레이터를 조회하고, 생성자 (또는 단 하나) B를 전달한 다음 데코레이터에서 메서드를 호출합니다.

과 비슷하다. BufferedReader 장식하다. Reader.

+0

나에게도 접근법은 이상하게 보일 것입니다. 바보 같을 수도 있습니다. :)? – Rimio

+0

글쎄, 내가 말했듯이, 나는 두 개의 매개 변수 (하나의 전송 객체로 묶여있을 수 있음)를 보내고, 하나의 매개 변수에 따라 메소드를 선택하고 두 번째 매개 변수에 따라 메소드의 매개 변수를 선택한다. – Thomas

+0

불완전한 답변을 드려 죄송합니다. 내가 추가하고 싶은 것은 다음과 같습니다.이 접근법은 로직 코드를 클라이언트로부터 멀리 떨어지게 유지하면서 객체와 함께 투명하게 작업하는 방법입니다. 함수 호출은 객체가 서버로 돌아가서 돌아갈지라도 클라이언트 코드에서 함수 호출처럼 보일 것입니다. – Rimio

2

각 C 클래스에는 부모 B (또는 A)에서 생성하는 생성자 또는 정적 createFromSuper가 있다고 가정합니다.

사용 가능한 모든 C가 등록 된 FactoryClass를 작성할 수 있습니다. 리플렉션을 사용하여 Map/Hashtable에서 각각의 B.class-> C.class 매핑을 기억하면서 "대체"하려는 C의 부모를 얻을 수 있습니다. 당신이 B를받을 때

그런 다음, 당신은/createFromSuper는 C를 반환 생성자가