2011-08-18 2 views
0

상속 공통 오브젝트를 확장하는 확장/형태의 다른 개체에 의해 상속 :PHP 대상체 - I은 기본 객체 (form_field_base)가 다른 오브젝트

class form_field_base { 
    // Lots of code 
} 
class form_field_text extends form_field_base { 
    // Lots of code 
} 
class form_field_email extends form_field_text { 
    // Extending the text object to update validation, and set input type="email" 
} 
class form_field_file extends form_field_base { 
    // Lots of code, for example uploading files 
} 

은 "form_field_base은"제공 폼 필드 타입이 모두 사용하는 도우미 메서드. 예를 들어 html() 함수는 특정 객체 (form_field_email :: html_input)를 호출하여 필드를 가져온 다음 표준 태그가있는 문자열에 넣습니다.

이 모든 객체는 많은 프로젝트에서 사용됩니다.

그러나 내가하고있는이 최신 프로젝트는 "form_field_base"객체가 일부 도움말 텍스트 설정을 허용하도록 사용자 정의되어 있어야하며, 다른 프로젝트에는 필요하지 않은 기능이 있어야하며 향후 프로젝트에서 수행 할 수있는 기능이있을 수 있습니다. 다르게.

어떻게 구성해야합니까?

이상적으로 나는 "form_field_base"의 완전한 사본을 가지지 않을 것입니다, 그것은 코드 중복을 야기 할 것입니다.

그리고 오버 헤드가 꽤처럼 보인다 더미 중간 오브젝트가하기 : (

class form_field_base_common { 
    // Lots of code 
} 
class form_field_base extends form_field_base_common { 
    // By default is empty 
} 

class form_field_text_common extends form_field_base { 
    // Lots of code 
} 
class form_field_text extends form_field_text_common { 
    // ... 
} 

class form_field_email_common extends form_field_text { 
    // Extending the text object to update validation, and set input type="email" 
} 
class form_field_email extends form_field_email_common { 
    // ... 
} 

class form_field_file_common extends form_field_base { 
    // Lots of code, for example uploading files 
} 
class form_field_file extends form_field_file_common { 
    // ... 
} 

하나 하나가 자동으로로드 인 자신의 파일의 가지고 촬영을하거나 프로젝트 특정 위치에서, 존재하는 경우, 또는 모든 프로젝트가 액세스 할 수있는 공통 폴더에서) ... 폼을 지원하기 위해 이미 발견, 열거 나 구문 분석되어야하는 파일은 이미 8 개입니다.

더 나은 방법이 있습니까?

+0

개인적인 방법과 데이터를 사용해 보셨습니까? 아니면 무슨 뜻이야? 동일한 코드베이스를 사용하는 다른 프로젝트에서 자손의 새로운 기능을 숨길 필요가 있습니까? – J0HN

+0

"form_field_base"가 이미 상당히 크기 때문에 더 많은 기능/코드를 하나의 작은 프로젝트 (많은 프로젝트에서 사용하고있을 때)에 추가하면 낭비되는 것처럼 보입니다. –

답변

1

상속 체인이 있고 공통 코드와 유형을 유지하면서 프로젝트 당 기본 구현을 수정하려는 경우 (기존 프로젝트를 심각하게 수정하지 않아도 됨).

가는 방법은 프로젝트의 특정 사용자 지정에서 일반적인 기능을 분리하는 것입니다. 프로젝트간에 사용자 정의를 공유 할 수있는 데코레이터 패턴을 사용하십시오.

당신의 상황은 기존의 모든 프로젝트입니다 :

A1 <- B <- C 

A1->a(), A1->a1(), 
B->a(), B->a1(), B->b() 
C->a(), C->a1(), C->b(), C->c() 

데코레이터 패턴은 각 개체의 장식을 작성해야합니다

A <- B <- C 

A->a() 
B->a(), B->b() 
C->a(), C->b(), C->c() 

새 프로젝트가 있어야한다 (프로젝트 1 말할 수) (A1, B1, C1)을 확장하려고합니다. 장식용 B1 및 C1에서 A1의 사용자 정의 방법을 사용할 수도 있기를 바랄 것이므로 원본 클래스와 동일한 방식으로 연결해야합니다.

A1 decorates A 
B1 decorates B 
C1 decorates C 

A1 <- B1 <- C1 

A1->a1() 
B1->a1() 
C1->a1() 
적절한 방법 각각 장식하고 꾸미는 소스 클래스 사이에 링크를 생성하고 위임 할 필요가있다, 그래서 당신은 여전히, 또한 장식 클래스에서 A, B, C의 기능을 원하는

:

A1 hosts a reference of A 
B1 hosts a reference of B 
C1 hosts a reference of C 

A1->a() ----> $this->myA->a(); 
B1->a() ----> $this->myB->a(); 
B1->b() ----> $this->myB->b(); 

모든 사용자 정의 프로젝트 1 방법은 직접 실행됩니다

A1->a1() ----> $this->a1(); 

을 새 프로젝트에서 당신이 다음 사용 1 :

A1 instead of A 
B1 instead of B 
C1 instead of C 

여러 개의 장식을 사용하기 위해 인스턴스를 전달할 수 있지만 A1, B1 및 C1은 A, B, C 인스턴스를 생성자에서 직접 만들 수 있습니다. 이 경우 IA, IB, IC 등의 적절한 인터페이스가 필요합니다. 그렇다면 A1은 정확한 A 또는 A1 또는 A2 또는 A3 일 수있는 setA(IA theA) 메서드를 가질 수 있습니다. 그러나 이것은 더 고급이며 데코레이터 패턴으로 인터넷 검색을하면 더 많은 정보를 얻을 수 있습니다. 인터페이스 및 다형성에 대한 경험. 전부


: 그것은

  • 원래 클래스와 위임에 각 사용자 정의 프로젝트

  • 링크 데코레이터를 데코레이터 체인을 만들기 같이

    1. 이 상속 체인을 남겨주세요 공통 기능.

    2. 사용자 정의 프로젝트의 원래 클래스 대신 데코레이터를 사용하십시오. 이제 원본과 동일하며 추가 할 추가 방법이 있습니다.

  • +0

    감사합니다 Jens, 아마 일을 약간 다르게했을 때, 이것은 기본적으로 어떻게 해결 했는가 ... 객체 지향 프로그래밍을 많이 사용할수록 더 복잡한 솔루션을 사용해야 할 수도 있습니다. 그냥 날). –

    0

    도움말 텍스트로 수행 할 작업에 따라 다릅니다. 아마도 다음과 같이 할 수 있습니다.

    1 - 원하는 목적으로 도움말 텍스트 개체를 만듭니다. 2 - form_field_base 클래스에 선택적 생성자 매개 변수를 만듭니다. 설정된 경우 도움말 텍스트 클래스의 전용 인스턴스입니다. 3 - 하위 클래스에서 도움말 텍스트 개체가 있는지 확인하십시오. 설정되어 있으면 추가 작업을 수행하십시오.

    아마도이 작업은 사용자가하려는 작업에 적합하지 않을 수 있습니다. 더 확신하지 못하면서, 내가 생각할 수있는 최선의 방법입니다!

    +0

    귀하의 제안에 감사드립니다. 귀하의 방법이 (여러 가지) 다양한 방법으로 처리 될 수있는 사용자 지정 도움말 텍스트를 허용하는 것처럼 기존 코드를 편집하지 않기를 바란다는 것을 인정해야합니다. 분명히있을 것입니다. 미래에 등장하는 다른 무작위 (one off) 기능도 이러한 종류의 편집을 필요로합니다. –

    0

    도움말 텍스트가없는 모든 양식 필드에 대한 기본 기본 클래스가있는 경우 그대로 두십시오. 대신 양식의 구성 요소를 나타내는 클래스를 만드십시오.

    abstract class FormComponent { 
        public __construct(FormField $field) { 
         $this->_field = $field; 
        } 
    
        public html() { 
         // Here you can choose any way to integrate the field's input HTML into 
         // the component's HTML. You can wrap it in a label, for example. 
         return $self->_get_html() . $self->_field->html_input(); 
        } 
    } 
    

    UPDATE : 이것은 높은 수준의 추상화 할 수 있습니다 당신은 form_field 상속 체인을 터치하지 않아도 그대로 당신이 그것을 남길 수 있습니다. 여기

    $field = new form_field_email($arguments); // Whatever arguments it takes 
    
    // Here the FormComponent_Email class inherits the FormComponent class 
    $component = new FormComponent_Email($field); 
    $component->set_hint('Some hint'); // Set your help text here 
    $component->set_label('Enter your email'); 
    
    // You can even add an error container if you wish 
    if ($some_email_error) { 
        $component->set_error('Your email has an error!'); 
    } 
    
    $component_html = $component->html(); 
    

    당신이 그 것이다 분야에 HTML 포장을 추가 할 수있는 이메일 구성 요소 클래스의 html 방법 내부 : 당신이 이런 식으로 할 경우, 당신은 다음과 같이 구성 요소 클래스로 인스턴스화 필드 개체를 삽입해야합니다 레이블, 힌트 컨테이너, 오류 컨테이너 및 필요한 모든 것을 표시하십시오.

    +0

    안녕 Igor, 이것은 매우 흥미로운 소리가 난다 ... 나는 문서를 보게 될 것이지만 어떻게 작동하는지에 대한 예제를 더 많이 가지고있다 ... 내가 "form_field_base "를 text/email/file/etc 클래스에서 가져 와서 어떻게 든 그 클래스 나 form_field_base로부터 상속받은 다른 (커스텀) 클래스로부터 상속받을 수 있습니다. –

    +0

    답변을 업데이트했습니다. 코드 스 니펫을 참조하십시오. 어떻게 정규 양식 객체를 사용하고 새로운 객체의 생성자로 전달하는지보십시오. –

    +1

    예를 들어서 고맙다고 말하고 싶습니다. 결국이 방법을 사용하지 않았습니다. 모든 필드에 추가 래퍼를 추가하기 때문에 (이 프로젝트에는 수 백 개의 필드가 포함되어 있습니다), 다른 프로젝트에서 도움이 될 수있는 좋은 해결책입니다 . –