>백엔드 개발 >PHP 튜토리얼 >하위 유형 다형성 - 런타임시 구현을 교환합니다

하위 유형 다형성 - 런타임시 구현을 교환합니다

尊渡假赌尊渡假赌尊渡假赌
尊渡假赌尊渡假赌尊渡假赌원래의
2025-02-25 18:15:16608검색

Subtype Polymorphism - Swapping Implementation at Runtime

코어 포인트

    객체 지향 설계에서의 하위 유형 다형성은 시스템이 계약 또는 인터페이스 세트를 정의한 다음 다른 하위 유형으로 구현할 수있는 능력을 말합니다. 이는 구현자가 예상 유형인지 확인하지 않고 특정 계약을 소비 할 수있는 확장 가능한 시스템을 설계하는 데 중요합니다.
  • 이 기사는 추가 캐시 드라이버를 개발하여 사용자 요구에 맞게 확장 할 수있는 삽입 가능한 캐시 구성 요소를 개발하여 하위 유형 다형성을 사용하는 것을 보여줍니다.
  • 캐시 구성 요소의 주요 기능은 클라이언트 코드를 변경하지 않고 런타임에서 다른 캐시 드라이버를 교체하는 기능입니다. 이는 캐시 계약을 정의 한 다음 다른 구현이 뒤 따르는 다형성을 이용하여 달성됩니다.
  • 캐시 구성 요소는 런타임에 백엔드를 전환 할 수있어 고도로 분리 된 모듈을 설계 할 때 다형성의 중요성을 강조합니다. 이를 통해 시스템의 다른 부분에서 취약성 또는 강성 관련 문제를 일으키지 않고 런타임에 쉽게 다시 연결할 수 있습니다.
  • 하위 유형 다형성은 시스템을보다 직교하고 스케일링하기가 더 쉽게 만들뿐만 아니라 오픈/폐쇄 원리 및 "인터페이스 지향 프로그래밍"원칙과 같은 핵심 패러다임을 위반할 가능성이 적습니다. 코드의 유연성과 재사용 가능성을 허용하는 객체 지향 프로그래밍의 기본 측면입니다.
  • 많은 사람들이 객체 지향 설계에서 상속과 다형성 사이의 상관 관계를 의심 할 수 있습니까? 아마도 대부분은 무지 나 좁은 사고로 인한 것일 수 있습니다. 그러나 여기에는 무시할 수없는 작은 문제가 있습니다. 상속의 논리를 이해하는 것은 간단하지만 다형성의 세부 사항을 탐구 할 때는 상황이 더욱 어려워집니다. “다형성”이라는 용어는 그 자체로 어려워지고 있으며, 학문적 정의는 다른 관점으로 가득 차 있기 때문에 실제로 그 뒤에있는 것을 이해하기가 더 어려워집니다. 매개 변수 다형성 및 임시 다형성 (일반적으로 메소드 재정의/과부하로 구현)과 같은 주변 개념은 일부 프로그래밍 언어로는 중요한 응용 프로그램이 있지만 설계에서는 초록에 특정 계약을 소비 할 수 있습니다. 구현자가 예상 유형인지 확인하지 않고 포기해야합니다. 요컨대, 대부분의 경우, 객체 지향 프로그래밍에서 다형성에 대한 일반적인 참조는 암시 적으로 계약 또는 인터페이스 세트 또는 인터페이스에 이어 다른 구현 세트를 정의하는 데 사용되는 시스템-유발 기능으로 간주됩니다. 이 "표준"다형성은 종종 계층의 구현자가 실제 계층이 있는지 여부에 관계없이 하위 유형으로 간주되기 때문에 종종 하위 유형 다형성이라고합니다. 예상대로 다형성의 본질을 이해하는 것은 학습 과정의 절반에 불과합니다. "코드"(대부분의 경우 장난감 코드의 저렴한 완곡입니다). 이 기사에서는 삽입 가능한 캐시 구성 요소를 개발하여 다형성이 제공하는 이점을 활용하는 방법을 보여 드리겠습니다. 추가 캐시 드라이버를 개발하여 핵심 기능을 나중에 요구에 맞게 확장 할 수 있습니다.
  • 구성 요소의 인터페이스와 구현을 정의합니다 선택할 수있는 옵션 메뉴는 확장 가능한 캐시 구성 요소를 구축 할 때는 결코 결여되지 않습니다 (이에 대해 회의적이라면 인기있는 프레임 워크 뒤에 무엇이 있는지 살펴보십시오). 그러나 여기에서 제공하는 구성 요소는 클라이언트 코드를 수정하지 않고 런타임에서 다른 캐시 드라이버를 교체 할 수있는 영리한 기능을 갖추고 있습니다. 그렇다면 개발 과정에서 많은 노력 없이이 작업을 수행 할 수 있습니까? 글쎄, 첫 번째 단계는 ... 예, 나중에 다른 구현에 이어 격리 된 캐시 계약을 정의하여 다형성의 이점을 이용합니다. 가장 기본적인 수준에서 위의 계약은 다음과 같습니다. 인터페이스는 일반적인 캐시 요소의 동작을 추상화하는 골격 계약입니다. 인터페이스를 사용하면 계약을 준수하는 특정 캐시 구현을 쉽게 만들 수 있습니다. 간단하고 이해하기 쉽기 때문에 설정 한 캐시 드라이버는 단지 린 듀오 일뿐입니다. 첫 번째는 파일 시스템을 캐시/GET 데이터의 기본 백엔드로 사용하고 두 번째는 APC 확장을 사용합니다. 무대 뒤에서. 다음은 파일 기반 캐시 구현입니다 수업의 운전 논리는 이해하기 쉽습니다. 지금까지 가장 관련성이 높은 것은 초기

    를 충실하게 달성하기 때문에 깔끔한 다형성 행동을 노출 시킨다는 것입니다. 이 능력은 달콤하고 매력적이지만, 여기서 목표를 고려하면 런타임에 백엔드를 전환 할 수있는 캐시 구성 요소를 만드는 것입니다. 교수 목적을 위해 추가 노력을 기울이고

    의 또 다른 간소화 된 구현을 생명에 가져 오겠습니다. 다음 구현은 인터페이스 계약을 준수하지만 이번에는 APC를 사용하여 번들링 방법을 확장하는 것입니다.

    <code class="language-php"><?php namespace LibraryCache;
    
    interface CacheInterface
    {
        public function set($id, $data);
        public function get($id);
        public function delete($id);
        public function exists($id);
    }</code>
    <<> 클래스는 경력에서 본 것 중 가장 눈부신 APC 래퍼가 아니며 메모리에서 데이터를 저장, 검색 및 삭제하는 데 필요한 모든 기능을 포장합니다. 우리는 특정 백엔드가 다형성으로 인해 런타임에 교환하기 쉬운 가벼운 캐시 모듈을 성공적으로 구현했을뿐만 아니라 향후 더 많은 백엔드를 추가하기가 매우 쉽기 때문에 스스로 박수를 보자.

    를 준수하는 다른 구현 만 작성하십시오. 그러나 실제 하위 유형 다형성은 인터페이스 구성을 통해 정의 된 계약을 구현함으로써 달성된다는 점을 강조해야합니다. 이는 매우 일반적인 접근법입니다. 그러나 아무것도 덜 정교회가되는 것을 막을 수 없으며 추상 클래스에 위치한 일련의 추상적 인 방법으로 선언 된 인터페이스를 전환하여 동일한 결과를 얻을 수 없습니다. 당신이 위험하다고 느끼고 그 우회로 가고 싶다면, 당신은 다음과 같이 계약과 해당 구현을 재구성 할 수 있습니다.

    <code class="language-php"><?php namespace LibraryCache;
    
    interface CacheInterface
    {
        public function set($id, $data);
        public function get($id);
        public function delete($id);
        public function exists($id);
    }</code>
    <code class="language-php"><?php namespace LibraryCache;
    
    class FileCache implements CacheInterface
    {
        const DEFAULT_CACHE_DIRECTORY = 'Cache/';
        private $cacheDir;
    
        public function __construct($cacheDir = self::DEFAULT_CACHE_DIRECTORY) {
            $this->setCacheDir($cacheDir);
        }
    
        public function setCacheDir($cacheDir) {
            if (!is_dir($cacheDir)) {
                if (!mkdir($cacheDir, 0644)) {
                    throw InvalidArgumentException('The cache directory is invalid.');
                }
            }
            $this->cacheDir = $cacheDir;
            return $this;
        }
    
        public function set($id, $data) {
            if (!file_put_contents($this->cacheDir . $id, serialize($data), LOCK_EX)) {
                throw new RuntimeException("Unable to cache the data with ID '$id'.");
            }
            return $this;
        }
    
        public function get($id) {
            if (!$data = unserialize(@file_get_contents($this->cacheDir . $id, false))) {
                throw new RuntimeException("Unable to get the data with ID '$id'.");
            }
            return $data;
        }
    
        public function delete($id) {
            if (!@unlink($this->cacheDir . $id)) {
                throw new RuntimeException("Unable to delete the data with ID '$id'.");
            }
            return $this;
        }
    
        public function exists($id) {
            return file_exists($this->cacheDir . $id);
        }
    }</code>
    <code class="language-php"><?php namespace LibraryCache;
    
    class ApcCache implements CacheInterface
    {
        public function set($id, $data, $lifeTime = 0) {
            if (!apc_store($id, $data, (int) $lifeTime)) {
                throw new RuntimeException("Unable to cache the data with ID '$id'.");
            }
        }
    
        public function get($id) {
            if (!$data = apc_fetch($id)) {
                throw new RuntimeException("Unable to get the data with ID '$id'.");
            } 
            return $data;
        }
    
        public function delete($id) {
            if (!apc_delete($id)) {
                throw new RuntimeException("Unable to delete the data with ID '$id'.");
            }
        }
    
        public function exists($id) {
            return apc_exists($id);
        }
    }</code>
    위에서 아래로, 이것은 실제로 다형성 접근법이며, 이는 이전에 논의 된 방법에 위배됩니다. 개인적으로 이것은 개인적인 진술 일뿐입니다. 계약을 정의하고 계약을 정의하고 여러 하위 유형이 공유하는 보일러 플레이트 구현을 캡슐화 할 때만 계약을 정의하고 추상 클래스를 사용하는 것이 좋습니다. 귀하의 요구에 가장 적합한 방법을 선택할 수 있습니다. 이 시점에서 커튼을 내려 놓고, 멋진 결말 의견을 쓰고, 인상적인 코딩 기술을 자랑하며, 캐시 구성 요소의 유연성에 대해 자랑 할 수 있었지만 그것은 우리에게 끔찍할 것입니다. 여러 구현을 소비 할 수있는 클라이언트 코드가있을 때, 다형성은 예상 계약을 충족하는 한 이러한 구현이 어떤 유형의 인스턴스인지 확인하지 않고 가장 유혹적인 측면을 나타냅니다. 캐시 구성 요소를 기본 클라이언트보기 클래스에 연결하여 측면을 밝히겠습니다.이를 통해 깔끔한 HTML 캐싱을 쉽게 수행 할 수 있습니다.

    캐시 드라이버를 사용하여

    를 사용하십시오 예제 캐시 모듈을 통한 HTML 출력 캐싱은 매우 간단하며 다른 시간에 긴 설명을 저장합니다. 전체 캐시 프로세스는 다음과 비슷한 간단한보기 클래스로 단순화 할 수 있습니다.

    가장 눈부신 사람은 클래스 생성자이며,

    메소드의 초기 구현자를 사용합니다. 마지막 메소드의 책임은 뷰의 템플릿을 출력 버퍼로 밀어 넣은 후 캐시하는 것이므로이 기능을 활용하고 전체 HTML 문서를 캐시하는 것이 좋습니다. 보기의 기본 템플릿에 다음 구조가 있다고 가정합니다.
    <code class="language-php"><?php namespace LibraryCache;
    
    abstract class AbstractCache
    {
        abstract public function set($id, $data);
        abstract public function get($id);
        abstract public function delete($id);
        abstract public function exists($id);
    }</code>
    이제 클래스의 인스턴스를보기에 제공하여 약간 재미 있고 문서를 캐시합시다.
    <code class="language-php"><?php namespace LibraryCache;
    
    class FileCache extends AbstractCache
    {
        // the same implementation goes here
    }</code>
    아주 좋아요? 하지만 잠깐! 위의 코드 스 니펫이 APC 확장이 설치되지 않은 시스템에서 폭발 할 것이라는 것을 언급하는 것을 잊어 버렸습니다 (Naughty System Administrator!). 이것은 신중하게 제작 된 캐시 모듈을 더 이상 재사용 할 수 없다는 것을 의미합니까? 이것은 파일 기반 드라이버가 작동하는 곳입니다. 불만을 수신하지 않고 클라이언트 코드에 넣을 수 있습니다.

    위의 단일 줄은 뷰가 공유 메모리 대신 파일 시스템을 사용하여 출력을 캐시합니다. 이 동적 스위칭 캐시 백엔드는 고도로 분리 된 모듈을 설계 할 때 다형성이 중요한 이유를 간략하게 보여줍니다. 이를 통해 우리는 시스템의 다른 부분에 취약성/강성 관련 아티팩트를 확산시키지 않고 런타임에 물건을 쉽게 다시 연결할 수 있습니다. CacheInterface 결론 render()

    다형성은 실제로 인생에서 좋은 것들 중 하나이며, 일단 이해하면, 그 사건없이 어떻게 할 수 있는지 궁금해합니다. 다형성 시스템은 본질적으로 더 직교, 확장이 쉬우 며 개방형/폐쇄 된 원칙 및 현명한 "인터페이스 지향 프로그래밍"원칙과 같은 핵심 패러다임을 위반하는 경향이 적습니다. 오히려 원시적이지만 캐시 모듈은 이러한 장점의 두드러진 예입니다. 다형성의 이점을 활용하기 위해 응용 프로그램을 리팩토링하지 않았다면 잭팟을 놓쳤 기 때문에 서두르는 것이 좋습니다! Fotolia의 사진

    서브 타입 다형성에 대한 FAQ (FAQ)

    하위 유형 다형성과 파라미터 다형성의 주요 차이점은 무엇입니까?

    포함 다형성으로도 알려진 하위 유형 다형성은 이름이 공공 슈퍼 클래스와 관련된 여러 다른 범주의 인스턴스를 나타내는 다형성의 한 형태입니다. 반면에 파라미터 다형성은 함수 또는 데이터 유형이 유형에 의존하지 않고 동일한 방식으로 값을 처리 할 수 ​​있도록합니다. 파라미터 다형성은 전체 정적 유형 안전을 유지하면서 언어를보다 표현력있게 만드는 방법입니다.

    하위 유형 다형성은 어떻게 Java에서 작동합니까? Java에서는 상속 및 인터페이스를 사용하여 하위 유형 다형성이 달성됩니다. 슈퍼 클래스 참조 변수는 서브 클래스 객체를 가리킬 수 있습니다. 이를 통해 Java는 런타임에 호출 할 방법을 결정할 수 있으며 이는 동적 메소드 스케줄링이라고합니다. 동적 다형성을 지원할 수있는 Java의 강력한 특징 중 하나입니다. 하위 유형 다형성의 예를 제공 할 수 있습니까?

    물론 Java의 간단한 예를 고려해 봅시다. "동물"이라는 슈퍼 클래스와 두 개의 서브 클래스 "개"와 "고양이"가 있다고 가정 해 봅시다. "개"와 "고양이"클래스는 "동물"클래스의 "사운드"방법을 다시 작성합니다. 이제 "개"또는 "고양이"객체를 가리키고 "사운드"메소드를 호출하는 "동물"참조를 작성하면 Java는 런타임에서 어떤 클래스의 "사운드"를 호출 해야하는지 결정합니다. 이것은 하위 유형 다형성의 예입니다.

    프로그래밍에서 하위 유형 다형성의 중요성은 무엇입니까?

    하위 유형 다형성은 객체 지향 프로그래밍의 기본적인 측면입니다. 코드의 유연성과 재사용 가능성을 허용합니다. 하위 유형 다형성을 사용하여 클래스 세트에 대한 공통 인터페이스를 설계 한 다음이 인터페이스를 사용하여 해당 클래스의 객체와 통합 된 방식으로 상호 작용할 수 있습니다. 이로 인해 더 깨끗하고 직관적이며 코드를 유지하기가 쉬워집니다.

    하위 유형 다형성과 Liskov 대체 원리의 관계는 무엇입니까?

    모든 프로그래밍 언어는 하위 유형 다형성을 지원합니까?

    모든 프로그래밍 언어가 하위 유형 다형성을 지원하는 것은 아닙니다. 주로 Java, C 및 C#과 같은 정적으로 입력 한 객체 지향 프로그래밍 언어의 기능입니다. Python 및 JavaScript와 같은 동적으로 입력 한 언어는 오리 유형이라고하는 다형 형태의 다형성을 가지고 있습니다.

    정적 다형성과 동적 다형성의 차이점은 무엇입니까?

    컴파일 타임 다형성으로도 알려진 정적 다형성은 방법 과부하를 통해 달성됩니다. 호출 방법에 대한 결정은 컴파일 시간에 이루어집니다. 한편, 런타임 다형성이라고도하는 동적 다형성은 방법 재 작성을 통해 구현된다. 전화 할 방법에 대한 결정은 런타임에 이루어집니다. 하위 유형 다형성은 동적 다형성이다.

    하위 유형 다형성에서 상향 변환의 개념을 설명 할 수 있습니까?

    upconversion은 파생 클래스 객체를 기본 클래스 객체로 처리하는 과정입니다. 하위 유형 다형성의 주요 측면입니다. 파생 클래스 객체를 상향 조정하면 기본 클래스에 정의 된 모든 메소드를 호출 할 수 있습니다. 그러나 메소드가 파생 클래스에서 다시 작성되면 다시 쓰기 버전이 호출됩니다.

    하위 유형 다형성의 맥락에서 하향 전환이란 무엇입니까?

    다운 변환은 UP 변환의 반대입니다. 슈퍼 클래스 객체를 서브 클래스로 변환하는 과정입니다. 서브 클래스에만 존재하는 메소드에 액세스 해야하는 경우 다운 변환을 사용할 수 있습니다. 그러나 변환되는 객체에 실제로 변환하는 유형이 없으면 ClassCastException을 유발할 수 있기 때문에 DownConversion이 위험 할 수 있습니다.

    하위 유형 다형성은 어떻게 코드의 재사용 성을 촉진합니까?

    하위 유형 다형성을 통해보다 일반적이고 재사용 가능한 코드를 작성할 수 있습니다. 서브 클래스 객체와 상호 작용하기 위해 슈퍼 클래스 참조를 사용하면 동일한 슈퍼 클래스의 서브 클래스에 속하는 한 다양한 객체에 대한 코드를 쓸 수 있습니다. 즉, 슈퍼 클래스를 사용하는 코드를 변경하지 않고도 새로운 서브 클래스를 추가 할 수있어 코드를보다 유연하고 유지 관리하기 쉽습니다.

위 내용은 하위 유형 다형성 - 런타임시 구현을 교환합니다의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.