생성자에서 setter 호출
생성자 (있는 경우)에서 뮤 테이터를 호출하는 장단점은 무엇입니까?
즉 :
public MyConstructor(int x) {
this.x = x;
}
대 :
public MyConstructor(int x) {
setX(x);
}
public void setX(int x) {
this.x = x;
}
선호하는 염기 서열? (이것은 숙제가 아닙니다. 생성자에서 인스턴스를 호출 할 때 항상 뮤 테이터를 호출하는 코딩 표준 문서를 찾아 보면 항상 그런 것이 아닙니다)
으로 개인적 대부분의 경우 변수를 직접 설정합니다 .
메소드 는 일반적으로 인스턴스가 호출 될 때까지 완전히 제거 될 것으로 예상됩니다. 특히, 생성자에서 재정의 된 메소드를 호출하는 것은 이해하기 어려운 코드와 발견하기 어려운 버그에 대한 레시피입니다.
즉, 나는 종종 클래스가 존재하는 경우에는 세터가 없을 경우에도 당신이 있지만, 어쨌든 불변 만들려고하지만 당신이 말한 이 어쨌든 생성자에서 설정합니다 :)
속성에 논리가있는 경우 setter 논리는 일반적으로 유효성 검사이며 관찰자에게 전파를 변경합니다. 일반적으로 메소드 시작시 생성자 매개 변수가 명시 적으로 확인 될 예정 이며 인스턴스가 완전히 생성되기 전에 전파가 발생하는 것을 생성 합니다.
생성자에 대한 두 가지 규칙을 따라 문제를 최소화하기 때문에 mutator를 사용하지 않습니다.
최종 클래스가 아닌 생성자는 final 또는 private 메서드 만 호출해야합니다 . 이 규칙을 무시하고 생성자가 최종 / 비공개가 아닌 메소드를 호출 한 다음을 수행합니다.
- 모든 메소드는 인스턴스가 완전히 초기화되면 가정하지 않아야합니다.
- (슈퍼 클래스 생성자와 해당 메서드를 호출한다는 사실 인식하지 못하는 하위 클래스)는 하위 클래스 생성자와 슈퍼의 생성자가 완전히 실행하고 가정합니다. 이 문제는 "사악한"생성 된 수퍼 클래스가 상속 계층 구조에서 더 깊어 질수록 악화됩니다.
추가인지 검증이 그만한 가치가 있습니까? 인스턴스 변수에만 값을 할당하는 간단한 뮤 테이터에 대한 예외를 허용 할 수 있습니다. 그럴 가치가없는 것처럼 보이지만 거의 없기 때문입니다.
[[@Jon Skeet는 그의 답변에서 언급합니다. "... 특히 생성자에서 재정의 된 메서드를 호출하는 것은 이해하기 어려운 코드와 발견하기 어려운 만드는 방법입니다." 그러나 나는이 문제의 결과가 충분히 강조되지 않습니다. ]]
는 생성자 this
인스턴스가 완전히 초기화되기 전에 누출에 대해주의해야 우리합니다 . 이전 규칙은 클래스 내부의 메서드와 바르에 액세스하는 하위 클래스에 관한 것이,완전히 초기화this
되기 전에 다른 클래스 및 유틸리티 함수로전달되는메서드 (최종 / 개인용)에도주의해야합니다this
. 생성자가 호출하는 비 개인 재정의 가능한 메소드가 많을수록this
.
최종이 아닌 비공개 메서드를 호출하는 생성자에 대한 일부 참조 :
http://www.javaspecialists.eu/archive/Issue210.html
나는 거의하지 않아 그 때문에 문제가 없었습니다. 특히 setter가 하위 클래스에서 재정의되거나 setter가 초기화 존재하지 않을 수있는 추가 메소드 호출을 시작하는 경우 의도하지 않은 결과가 중요 수도 있습니다.
생성자 내 에서 ,, 메소드 를 호출하는 것은 사용자에게 달려만이 메소드는 하위 클래스에서 재정의 될 수 있고 실제로이 메소드의 재정의 된 버전 호출되기 때문에 생성자 내에서 호출되기 때문에 가장 좋습니다 ( 동작을 사용하는 경우). .public
static
non-final
예를 들면 :
public class Foo {
public Foo() {
doSmth(); // If you use polymorphic behavior this method will never be invoked
}
public void doSmth() {
System.out.println("doSmth in super class");
}
public static void main(String[] args) {
new Bar(200);
}
}
class Bar extends Foo {
private int y;;
public Bar(int y) {
this.y = y;
}
@Override
public void doSmth() { // This version will be invoked even before Barr object initialized
System.out.println(y);
}
}
0을 인쇄합니다.
자세한 내용은 Bruce Eckel "Thinking in Java" 장 "Polymorphism"을 참조하십시오.
세터를 어떻게 처리 하느냐에 따라 다릅니다. 클래스가 파생 될 수 있다고 믿는 경우 다른 곳에서 동작을 재정의 할 수 있도록 이러한 호출을 허용 할 수 있습니다. 그렇지 않으면 그대로 설정할 수 있습니다.
물론 setter를 명시 적으로 호출하도록 허용하면 설정 중에 추가 동작을 삽입하는 방법도 제공됩니다 (예 : 필요한 경우 보안 적용).
setter가보다 복잡한 작업을 수행하지 않는 한 this.x = x
변수를 직접 설정합니다. 매개 변수는 인스턴스 변수에 직접 매핑되며, 저에게는 더 많은 의도를 보여줍니다.
내 선호는 몇 가지 이유로 생성자에서 직접 설정하는 것입니다. 첫째 this.x = x;
, 같은 일을 수행하는 별도의 메서드를 호출하는 것보다 더 명확하지는 않지만 같은 것은 분명합니다. 둘째, 메소드가 final로 표시되지 않는 한 잠재적으로 재정의되었을 수 있으며 생성자에서 잠재적으로 재정의 된 메서드를 호출하는 것은 내 책에서 큰 금지입니다. 셋째, 대부분의 메서드는 일반적으로 개체가 생성되는 도중이 아니라 실행 중일 때 이미 완료되었다고 가정합니다. 이 간단한 경우에 문제가 발생해서는 안되지만 더 복잡한 경우에는 추적하는 데 오랜 시간이 걸리는 심각한 미묘한 버그가 발생할 수 있습니다.
어디에서나 setter / getter를 사용하는 주된 주장은 필드의 이름, 정의, getter / setter 메서드를 3 곳에서 변경하여 필드 이름을 바꿀 수 있으며 모두 컴파일되고 정상이어야한다는 것입니다. 괜찮은 현대 IDE는 간단한 키보드 단축키로 그러한 필드의 모든 발생의 이름을 바꿀 것이기 때문에 그 주장은 요즘 무효입니다.
우리의 코딩 표준이 접근 자 (비공개 일 수도 있음)의 사용을 요구하는 한 가지 이유가 있습니다. 어떤 코드가 필드를 변경하는지 빠르게 확인하려면 Eclipse에서 setter에 대한 호출 계층 구조를 가져 오면됩니다!
이는 200 만 줄의 코드에 도달 한 코드베이스에서 엄청난 시간을 절약하고 리팩토링도 쉽게 해줍니다.
나도 신경 쓰지 않고 강한 편견을 가지고 있지 않습니다 [그리고 엄격한 기준을 고수하지도 않습니다]. 단지 당신의 판단을 사용하십시오. 그러나 setter를 사용하는 경우 클래스를 재정의하는 사람은 객체가 완전히 생성되지 않을 수 있음을 알아야합니다. 즉, setter의 추가 코드가 this
참조 를 게시 할 수 없도록해야 합니다.
Setter는 표준 범위 검사 등에 유용 할 수 있으므로 입력을 확인하는 추가 코드가 필요하지 않습니다. 다시 세터를 사용하는 것은 약간 더 더러운 접근 방식입니다.
필드를 사용하면 명백한 이점이 있으며 (예 : 하위 클래스가 악의적으로 동작을 변경할 수 없도록하는 등) 일반적으로 선호됩니다. 도서관에서.
실제로 c-tor는 객체를 생성하는 3 가지 가능한 방법 중 하나입니다 (직렬화 + 복제는 다른 2). 일부 일시적인 상태는 c-tor 외부에서 처리해야 할 수 있으므로 필드 대 setter에 대해 고려해야 할 사항이 있습니다. (편집, 또 다른 방법이 있습니다 : 안전하지 않지만 직렬화가 사용하는 것입니다)
참고 URL : https://stackoverflow.com/questions/4893558/calling-setters-from-a-constructor
'ProgramingTip' 카테고리의 다른 글
MongoDB 연결에 대한 .NET 모범 사례? (0) | 2020.12.04 |
---|---|
Python에서 jquery와 같은 HTML 구문 분석? (0) | 2020.12.04 |
console.log () 호출을 Jasmine 테스트의 표준 출력으로 리디렉션 (0) | 2020.12.04 |
Files.ReadAllLines를 비 동기화하고 결과를 찾는 방법은 무엇입니까? (0) | 2020.12.04 |
활성 탭을 사용하는 모든 탭을 닫으시겠습니까? (0) | 2020.12.04 |