디자인 모델 6 대 원칙 의 2 - 리 씨 교체

리 씨 교체 원칙
내 가 이 원칙 을 처음 봤 을 때 와 마찬가지 로 이 원칙 의 이름 에 의문 이 가득 한 사람 이 많 을 것 이다.사실은 이 원칙 이 1988 년 에 매사 추 세 츠 공과 대학의 한 성 안의 여자 (Barbara Liskov) 가 제 기 했 기 때문이다.
정의 1: 각 유형 이 T1 인 대상 o1 에 대해 T2 인 대상 o2 가 있 으 면 T1 으로 정 의 된 모든 프로그램 P 가 모든 대상 o1 에서 o2 로 대 체 될 때 프로그램 P 의 행동 에 변화 가 없 으 면 유형 T2 는 유형 T1 의 하위 유형 입 니 다.
정의 2: 모든 인용 기본 클래스 는 하위 클래스 의 대상 을 투명 하 게 사용 해 야 합 니 다.
문제 의 유래: 기능 P1 이 있 고 클래스 A 로 이 루어 집 니 다.현재 기능 P1 을 확장 해 야 합 니 다. 확장 후의 기능 은 P 입 니 다. 그 중에서 P 는 기 존의 기능 P1 과 새로운 기능 P2 로 구성 되 어 있 습 니 다.새로운 기능 P 는 클래스 A 의 하위 클래스 B 로 이 루어 지 며, 하위 클래스 B 는 새로운 기능 P2 를 완성 하면 서 기 존 기능 인 P1 이 고장 날 수 있다.
해결 방안: 계승 을 사용 할 때 리 씨 교체 원칙 에 따른다.클래스 B 가 클래스 A 를 계승 할 때 새로운 방법 을 추가 하여 새로운 기능 P2 를 완성 하 는 것 을 제외 하고 부모 클래스 A 의 방법 을 다시 쓰 지 말고 부모 클래스 A 의 방법 을 다시 싣 지 않도록 한다.
계승 은 이러한 의 미 를 포함한다. 아버지 류 에서 이미 실 현 된 방법 (추상 적 인 방법 에 비해) 은 실제 적 으로 일련의 규범 과 계약 을 설정 하 는 것 이다. 모든 자 류 는 반드시 이런 계약 을 따라 야 한다 고 강요 하지 않 지만 서브 류 가 이런 비 추상 적 인 방법 에 대해 임의로 수정 하면 전체 계승 체계 에 파 괴 를 초래 할 것 이다.리 씨 교체 원칙 은 이런 의 미 를 표현 한 것 이다.
계승 은 대상 을 대상 으로 하 는 3 대 특성 중 하나 로 프로그램 설계 에 큰 편 의 를 가 져 오 는 동시에 단점 도 가 져 왔 다.예 를 들 어 계승 을 사용 하면 프로그램 에 침입 성 을 가 져 올 수 있 고 프로그램의 이식 성 이 낮 아 지 며 대상 간 의 결합 성 을 증가 할 수 있다. 만약 에 한 가지 유형 이 다른 유형 에 의 해 계승 된다 면 이런 유형 이 수정 이 필요 할 때 모든 하위 유형 을 고려 해 야 하고 부모 류 가 수정 되면 모든 하위 기능 이 고장 날 수 있다.
예 를 들 어 상속 의 위험 을 설명 하려 면 우 리 는 두 가지 가 상쇄 되 는 기능 을 완성 하고 류 A 가 책임 을 져 야 한다.
class A{
	public int func1(int a, int b){
		return a-b;
	}
}

public class Client{
	public static void main(String[] args){
		A a = new A();
		System.out.println("100-50="+a.func1(100, 50));
		System.out.println("100-80="+a.func1(100, 80));
	}
}

실행 결과:
100-50=50
100-80=20

그 후에 우 리 는 새로운 기능 을 추가 해 야 한다. 두 수 를 더 한 다음 에 100 과 화 해 를 구 하 는 것 은 류 B 가 책임 진다.즉, 클래스 B 는 두 가지 기능 을 완성 해 야 합 니 다.
두 수가 서로 줄다
4. 567917. 두 수 를 더 한 다음 에 100 을 더 합 니 다
클래스 A 는 첫 번 째 기능 을 실 현 했 기 때문에 클래스 B 는 클래스 A 를 계승 한 후에 두 번 째 기능 만 완성 하면 됩 니 다. 코드 는 다음 과 같 습 니 다.
class B extends A{
	public int func1(int a, int b){
		return a+b;
	}
	
	public int func2(int a, int b){
		return func1(a,b)+100;
	}
}

public class Client{
	public static void main(String[] args){
		B b = new B();
		System.out.println("100-50="+b.func1(100, 50));
		System.out.println("100-80="+b.func1(100, 80));
		System.out.println("100+20+100="+b.func2(100, 20));
	}
} 

클래스 B 완료 후 실행 결과:
100-50=150
100-80=180
100+20+100=220

우 리 는 원래 정상적으로 작 동 하 던 상쇄 기능 에 오류 가 발생 한 것 을 발견 했다.그 이 유 는 클래스 B 가 방법 에 이름 을 지 을 때 본의 아니 게 부모 클래스 의 방법 을 다시 써 서 상쇄 기능 을 실행 하 는 모든 코드 가 클래스 B 재 작성 후의 방법 을 호출 하여 원래 정상 적 인 기능 을 실행 하 는 데 오류 가 발생 했 기 때문이다.이 사례 에 서 는 기 존 클래스 A 가 완 성 된 기능 을 인용 해 하위 클래스 B 로 바 꾼 뒤 이상 이 발생 했다.실제 프로 그래 밍 에서 우 리 는 부 류 를 다시 쓰 는 방법 을 통 해 새로운 기능 을 완성 하 는 경우 가 많다. 이렇게 쓰 면 간단 하지만 전체 계승 시스템 의 재 활용 성 이 비교적 떨어진다. 특히 다 형 을 자주 사용 할 때 프로그램 이 실 수 를 할 확률 이 매우 높다.만약 에 부 류 를 다시 쓰 는 방법 이 필요 하 다 면 비교적 통용 되 는 방법 은 원래 의 부 류 와 자 류 는 모두 더욱 통속 적 인 기 류 를 계승 하고 원래 의 계승 관 계 를 없 애고 의존, 집적, 조합 등 관 계 를 대체 하 는 것 이다.
리 씨 교체 원칙 은 통속 적 으로 말 하면 자 류 는 부류 의 기능 을 확장 할 수 있 으 나 부류 의 원래 기능 을 바 꿀 수 없다 는 것 이다.그것 은 다음 과 같은 4 가지 의 미 를 포함한다.
4. 567917. 자 류 는 아버지 류 의 추상 적 인 방법 을 실현 할 수 있 지만 아버지 류 의 비 추상 적 인 방법 을 덮어 서 는 안 된다
4. 567917. 하위 클래스 에서 자신 만 의 독특한 방법 을 증가 시 킬 수 있다
4. 567917. 하위 클래스 의 방법 으로 부모 클래스 의 방법 을 다시 불 러 올 때 방법의 선행 조건 (즉, 방법의 형 삼) 은 부모 클래스 방법의 입력 매개 변수 보다 더욱 느슨 하 다
4. 567917. 자 류 의 방법 으로 아버지 류 의 추상 적 인 방법 을 실현 할 때 방법의 사후 조건 (즉, 방법의 반환 값) 은 아버지 류 보다 더욱 엄격 하 다
신기 하 게 도 우 리 는 자신의 프로 그래 밍 에서 리 씨 교체 원칙 을 위반 하고 프로그램 이 잘 달 리 는 것 을 발견 할 수 있 기 때문이다.그래서 모두 가 이런 의문 을 갖 게 될 것 이다. 만약 내 가 리 씨 교체 원칙 을 따 르 지 않 으 면 어떤 결과 가 있 을 까?
결 과 는 당신 이 쓴 코드 에 문제 가 생 길 확률 이 크게 증가 한 다 는 것 이다.

좋은 웹페이지 즐겨찾기