programing

Java에서 보호된 스태틱을 사용하지 않는 이유

yoursource 2022. 11. 1. 22:37
반응형

Java에서 보호된 스태틱을 사용하지 않는 이유

자바에서 클래스 변수를 덮어쓸 수 있는 방법이 있나요?36표를 얻은 첫 번째 코멘트는 다음과 같다.

시 라 도?protected static, 도망쳐!

Can anyone explain why is a 왜 그런지는 누가 설명해주실 수 있나요?protected static찡그렸나요?눈살을 찌푸리게?

그것은 직접적인 문제라기보다는 문체적인 것이다.그것은 당신이 수업에서 무슨 일이 일어나고 있는지 제대로 생각하지 못했음을 암시한다.

Think about what 생각해 봐static means:다음을 의미합니다.

이 변수는 클래스 수준에서 존재하며 각 인스턴스에 개별적으로 존재하지 않으며 나를 확장하는 클래스에 독립적 존재도 없습니다.

Think about what 생각해 봐protected means:다음을 의미합니다.

이 변수는 이 클래스, 동일한 패키지의 클래스 및 나를 확장하는 클래스에서 볼 수 있습니다.

그 두 가지 의미는 정확히 서로 배타적이지는 않지만 꽤 비슷하다.

이 둘을 함께 사용할 수 있는 유일한 경우는 확장하도록 설계된 추상 클래스가 있고 확장 클래스가 원본에 정의된 상수를 사용하여 동작을 수정할 수 있는지 여부입니다.그런 종류의 배치는 아마도 매우 지저분하게 끝날 것이고 수업 설계의 약점을 나타낼 것이다.

대부분의 경우 상수를 공개로 하는 것이 좋습니다.그렇게 하면 모든 것이 깨끗해지고 사람들이 보다 유연하게 하위 분류할 수 있기 때문입니다.다른 어떤 것과도 상당히 다른 많은 경우에서 구성은 상속보다 선호되는 반면 추상적인 계층은 상속을 강요한다.

이것이 어떻게 사물을 파괴할 수 있는지, 변수가 독립된 존재를 가지지 않는 것이 무엇을 의미하는지 설명하려면 다음 예제 코드를 사용해 보십시오.

public class Program {
    public static void main (String[] args) throws java.lang.Exception {
        System.out.println(new Test2().getTest());
        Test.test = "changed";
        System.out.println(new Test2().getTest());
    }
}

abstract class Test {
    protected static String test = "test";
}

class Test2 extends Test {
    public String getTest() {
        return test;
    }
}

결과가 표시됩니다.

test
changed

직접 사용해 보세요.https://ideone.com/KM8u8O

클래스 급?Test2 is able to access the static member 스태틱 멤버에 접속할 수 있다test부에서Test이름을 부여하지 않아도 됩니다. 그러나 상속자가 상속되지 않습니다.이름을 한정할 필요는 없지만 자체 복사본을 상속하거나 가져오지 않습니다.메모리에서 정확한 개체를 찾고 있습니다.메모리의 동일한 오브젝트를 보고 있습니다.

그것은 모순적이기 때문에 눈살을 찌푸리게 된다.

만들기protected는 패키지 내에서 사용되는지 서브클래스 내에서 상속되는지를 나타냅니다.

''static를 클래스의 멤버로 하여 상속 의도를 없앱니다.이는 패키지 내에서 사용될 의도만 남겨두고 있습니다.package-private을 사용하다

될 수 유일한 상황은 "JavaF"와 같은 경우).Application#launch서브클래스에서만 기동할 수 있기를 희망하고 있습니다.는, 그 도 「어느쪽인가」, 「어느쪽인가」로 해 .final숨는 것을 허락하지 않는다.그러나 이는 "표준"이 아니며, 애플리케이션을 실행하는 새로운 방법을 추가함으로써 복잡성을 증가시키지 않기 위해 구현된 것일 수 있습니다.

각 수식자의 액세스레벨을 표시하려면 , 다음을 참조해 주세요.Java 튜토리얼 - 클래스 멤버에 대한 접근 제어

나는 왜 이것이 눈살을 찌푸리게 해야 하는지 특별한 이유를 모르겠다.항상 같은 동작을 실현하기 위한 대안이 있을 수 있으며, 이러한 대안이 보호되는 정적 방법보다 "더 나은"지 여부는 실제 아키텍처에 따라 달라집니다.단, 적어도 보호되는 스태틱 방식이 타당한 예로는 다음과 같은 것이 있습니다.

(패키지로 protectedclear를 클릭합니다.

package a;
import java.util.List;

public abstract class BaseClass
{
    public Integer compute(List<Integer> list)
    {
        return computeDefaultA(list)+computeDefaultB(list);
    }

    protected static Integer computeDefaultA(List<Integer> list)
    {
        return 12;
    }
    protected static Integer computeDefaultB(List<Integer> list)
    {
        return 34;
    }
}

그 결과:

package a.b;

import java.util.List;

import a.BaseClass;

abstract class ExtendingClassA extends BaseClass
{
    @Override
    public Integer compute(List<Integer> list)
    {
        return computeDefaultA(list)+computeOwnB(list);
    }

    private static Integer computeOwnB(List<Integer> list)
    {
        return 56;
    }
}

다른 파생 클래스:

package a.b;

import java.util.List;

import a.BaseClass;

abstract class ExtendingClassB extends BaseClass
{
    @Override
    public Integer compute(List<Integer> list)
    {
        return computeOwnA(list)+computeDefaultB(list);
    }

    private static Integer computeOwnA(List<Integer> list)
    {
        return 78;
    }
}

protected static수식어는 다음과 같이 정당화될 수 있습니다.

  • 방법은 다음과 같습니다.static인스턴스 변수에 의존하지 않기 때문입니다.이러한 방법은 다형성 방법으로 직접 사용하는 것이 아니라 보다 복잡한 연산의 일부인 기본 구현을 제공하는 "유틸리티" 방식으로 실제 구현의 "구성 요소" 역할을 합니다.
  • 방법은 다음과 같습니다.public이는 구현 세부사항이기 때문입니다.그리고 그들은 그럴 수 없다.private왜냐하면 그들은 확장된 계층에 의해 불려져야 하기 때문이다.또한 다른 패키지의 확장 클래스에 액세스할 수 없기 때문에 "기본" 가시성을 가질 수 없습니다.

(편집: 원래의 코멘트는 필드만을 참조했을 뿐 메서드는 참조하지 않았다고 생각할 수 있습니다.단, 너무 일반적이었습니다.)

스태틱 하는 클래스, 「」는 「」( 「」)에 표시됩니다.따라서protected static 을 가지다static코드 작성자가 오해하고 있음을 나타냅니다.

것은 .protected static패키지와 선언 클래스의 모든 서브클래스에 대해 표시할 수 있는 정적 변수 또는 메서드를 원하는 경우 계속 작성하십시오.protected static.

어떤 사람들은 일반적으로 사용을 피한다.protected여러 가지 이유로 어떤 사람들은 최종적이지 않다고 생각한다.static모든 수단(개인적으로는 후자에 어느 정도 공감한다)을 피해야 하기 때문에, 나는 그 조합이 있다고 생각한다.protected그리고.static양쪽 그룹에 속하는 그룹에는 불량^2로 보여야 합니다.

보호는 하위 클래스에서 사용할 수 있도록 사용됩니다.동일한 변수에 액세스할 수 있으므로 구체적인 클래스의 컨텍스트에서 사용할 때 보호된 정적을 정의하는 것은 논리가 없습니다.그러나 컴파일러는 슈퍼클래스 정적 변수에 정적 방식으로 액세스하라는 경고를 보냅니다.

대부분의 사람들이 대답했듯이:

  • protected'패키지-프라이빗 + 서브클래스에 대한 가시성 - 속성/행동이 상속됨'을 의미합니다.
  • static즉, '인스턴스의 반대 - 클래스 속성/행동, 상속되지 않음'을 의미합니다.

그러므로 그들은 약간 모순되고 양립할 수 없다.

그러나 최근 이 두 가지를 함께 사용하는 것이 타당할 수 있는 사용 사례를 발견했습니다.불변형 타입의 부모로서 서브타입에 공통되는 속성 묶음을 가지는 클래스를 작성한다고 가정합니다.불변성을 적절히 구현하고 가독성을 유지하기 위해 Builder 패턴을 사용할 수도 있습니다.

package X;
public abstract class AbstractType {
    protected Object field1;
    protected Object field2;
    ...
    protected Object fieldN;

    protected static abstract class BaseBuilder<T extends BaseBuilder<T>> {
        private Object field1; // = some default value here
        private Object field2; // = some default value here
        ...
        private Object fieldN; // = some default value here

        public T field1(Object value) { this.field1 = value; return self();}
        public T field2(Object value) { this.field2 = value; return self();}
        ...
        public T fieldN(Object value) { this.fieldN = value; return self();}
        protected abstract T self(); // should always return this;
        public abstract AbstractType build();
    }

    private AbstractType(BaseBuilder<?> b) {
        this.field1 = b.field1;
        this.field2 = b.field2;
        ...
        this.fieldN = b.fieldN;
    }
}

그리고 왜? 왜냐면 난 비추상적 서브타입의AbstactType자체 비추상적 빌더를 구현하고 외부에 배치되어 있습니다.package X접근하여 재사용할 수 있다BaseBuilder.

package Y;
public MyType1 extends AbstractType {
    private Object filedN1;

    public static class Builder extends AbstractType.BaseBuilder<Builder> {
        private Object fieldN1; // = some default value here

        public Builder fieldN1(Object value) { this.fieldN1 = value; return self();}
        @Override protected Builder self() { return this; }
        @Override public MyType build() { return new MyType(this); }
    }

    private MyType(Builder b) {
        super(b);
        this.fieldN1 = b.fieldN1;
    }
}

물론, 우리는 그것을 만들 수 있다.BaseBuilder하지만 또 다른 모순된 발언에 직면하게 됩니다.

  • 비인스턴트 클래스(추상)가 있습니다.
  • 우리는 그것을 위해 공공 건축가를 제공한다.

그래서 와 의 구축자 모두 모순된 진술을 결합합니다.그것은 개인적인 취향의 문제이다.

하지만, OOD와 OOP의 세계에서는 더 부자연스럽게 느껴지기 때문에 나는 여전히건축가를 선호합니다!

가지고 있어도 전혀 문제될 것이 없다protected static많은 사람들이 간과하고 있는 것은, 통상적인 상황에서는 드러내고 싶지 않은 정적 방법의 테스트 케이스를 쓰는 것입니다.유틸리티 클래스의 정적 메서드에 대한 테스트 작성에 특히 유용합니다.

언급URL : https://stackoverflow.com/questions/24289070/why-we-should-not-use-protected-static-in-java

반응형