Java 이름 숨기기:하드웨이
나는 이름 감추기에 매우 어려운 문제가 있다.다음은 이 문제를 설명하는 간략화된 버전입니다.
클래스가 있습니다.org.A
package org;
public class A{
public class X{...}
...
protected int net;
}
다음에 요.net.foo.X
package net.foo;
public class X{
public static void doSomething();
}
.이러한계급은우리나라를 입니다.A
하고 net.foo.X.doSomething()
package com.bar;
class B extends A {
public void doSomething(){
net.foo.X.doSomething(); // doesn't work; package net is hidden by inherited field
X.doSomething(); // doesn't work; type net.foo.X is hidden by inherited X
}
}
시시시, 시시이이이 이다다다할 수 .X
상속된 유형에 의해 숨겨지기 때문입니다.할 수 .net.foo.X
, 냐냐net
는 상속된 필드에 의해 숨겨집니다.
B
에 있다; ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」net.foo.X
★★★★★★★★★★★★★★★★★」org.A
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★!
유일한 솔루션은 다음과 같습니다. 할 수 .X.doSomething()
; 하지만 이 클래스는 이름 충돌 때문에 존재할 뿐이고, 그것은 매우 지저분해 보인다!가 직접 할 수 있는 ?X.doSomething()
부에서B.doSomething()
????
글로벌 네임스페이스, 로, 임, 벌 스 정 는 할 : 있 언 in a예 namespace,수(,지ifyingg that the e spec어네를스이페 globalglobal::
C# 또는 C# 는)::
in C++, I could simply prefix C++에서는, 간단하게 프레픽스를 붙일 수 있습니다.net
이 글로벌 접두사가 있지만 Java는 그것을 허용하지 않습니다.이 글로벌 프레픽스를 사용하는데 Java에서는 허용되지 않습니다.
You can cast a 캐스트 할 수 있습니다.null
(타깃 오브젝트는 정적 메서드의 호출에 관여하지 않기 때문에 동작합니다).
((net.foo.X) null).doSomething();
이 방법에는 다음과 같은 메리트가 있습니다.
- 없는
net.foo.X
- 가 없다(을 알 수 )
B
'아까', '아까', '아까', '아까', '아까', '아까',import static
것 같다'는 안 될 것 같아요. - (좋은 생각일 수도 있지만) 대표자 클래스의 도입은 필요 없습니다.
- 리플렉션 API로 작업하는 데 따른 오버헤드나 복잡성이 필요하지 않습니다.
단점은 이 코드가 정말 끔찍하다는 거야!제게는, 경고가 생성되고, 그것은 일반적으로 좋은 일입니다.하지만 완전히 비현실적인 문제를 해결하기 위해,
@SuppressWarnings("static-access")
컴파일러를 셧다운합니다.
아마도 가장 간단한 방법(꼭 가장 쉬운 방법은 아님)은 위임 클래스를 사용하는 것입니다.
import net.foo.X;
class C {
static void doSomething() {
X.doSomething();
}
}
그리고...
class B extends A {
void doX(){
C.doSomething();
}
}
유연합니다. 하게 할 수 , 이 두 가지 같은 방식으로 합니다.이치게다가, 양쪽 모두에서, 거의 같은 방법으로 동작합니다.static
메서드 및 인스턴스화된 객체
위임 객체에 대한 자세한 내용은 http://en.wikipedia.org/wiki/Delegation_pattern를 참조하십시오.
스태틱 Import를 사용할 수 있습니다.
import static net.foo.X.doSomething;
class B extends A {
void doX(){
doSomething();
}
}
조심해B
그리고.A
명명된 메서드가 포함되어 있지 않습니다.doSomething
적절한 작업 방법은 정적 가져오기를 사용하는 것이지만, 최악의 경우 완전 수식 이름을 알고 있는 경우 반사를 사용하여 클래스의 인스턴스를 생성할 수 있습니다.
Java: 기본 생성자가 없는 클래스의 newInstance
그런 다음 인스턴스에서 메서드를 호출합니다.
또는 메서드 자체를 반영하여 호출합니다.리플렉션을 사용한 정적 메서드 호출
Class<?> clazz = Class.forName("net.foo.X");
Method method = clazz.getMethod("doSomething");
Object o = method.invoke(null);
물론 이것들은 분명히 최후의 수단이다.
정답은 아니지만 X의 인스턴스를 만들고 해당 인스턴스의 정적 메서드를 호출할 수 있습니다.그렇게 하는 것이 (더러운 것은 인정합니다) 당신의 방법일 것입니다.
(new net.foo.X()).doSomething();
캐스트하거나 이상한 경고를 억제하거나 중복 인스턴스를 생성할 필요가 없습니다.서브클래스를 통해 부모클래스의 스태틱메서드를 호출할 수 있다는 사실을 이용한 트릭입니다.(이쪽의 해킹 솔루션과 유사합니다.)
이런 클래스만 만들면 됩니다.
public final class XX extends X {
private XX(){
}
}
(이 최종 클래스의 프라이빗컨스트럭터는 실수로 이 클래스의 인스턴스를 만들지 않도록 합니다).
그럼 전화하셔도 됩니다.X.doSomething()
경유:
public class B extends A {
public void doSomething() {
XX.doSomething();
}
모든 파일이 동일한 폴더에 있는 경우 gobal namespace를 가져오려고 하면 어떻게 됩니까?(http://www.beanshell.org/javadoc/bsh/class-use/NameSpace.html)
package com.bar;
class B extends A {
public void doSomething(){
com.bar.getGlobal().net.foo.X.doSomething(); // drill down from the top...
}
}
이것이 상속보다 구성이 더 나은 이유 중 하나이다.
package com.bar;
import java.util.concurrent.Callable;
public class C implements Callable<org.A>
{
private class B extends org.A{
public void doSomething(){
C.this.doSomething();
}
}
private void doSomething(){
net.foo.X.doSomething();
}
public org.A call(){
return new B();
}
}
저는 Strategy 패턴을 사용합니다.
public interface SomethingStrategy {
void doSomething();
}
public class XSomethingStrategy implements SomethingStrategy {
import net.foo.X;
@Override
void doSomething(){
X.doSomething();
}
}
class B extends A {
private final SomethingStrategy strategy;
public B(final SomethingStrategy strategy){
this.strategy = strategy;
}
public void doSomething(){
strategy.doSomething();
}
}
이제 의존 관계도 분리되었으므로 단위 테스트를 작성하기가 더 쉬워집니다.
언급URL : https://stackoverflow.com/questions/24572214/java-name-hiding-the-hard-way
'programing' 카테고리의 다른 글
Java의 DAO(Data Access Object) (0) | 2022.12.24 |
---|---|
2003: '127.0.0.1:3306'에서 MySQL 서버에 연결할 수 없음(99 요청된 주소를 할당할 수 없음) (0) | 2022.12.24 |
문자열에서 숫자가 아닌 모든 문자를 제거합니다. [^0-9]이(가) 예상과 일치하지 않습니다. (0) | 2022.12.24 |
MariaDB, Larabel 5.4 커넥터가 있습니까? (0) | 2022.12.24 |
PHP 날짜 시간 이후 경과된 시간을 찾는 방법 (0) | 2022.12.24 |