Programing

Objective-C에서 상속과 범주의 차이점은 무엇입니까?

lottogame 2020. 12. 15. 08:12
반응형

Objective-C에서 상속과 범주의 차이점은 무엇입니까?


어떤 사람이 Objective C의 범주와 상속의 차이점을 설명해 줄 수 있습니까? 나는 Wikipedia의 항목을 읽었 으며 카테고리에 대한 토론은 상속과 다르지 않습니다. 또한 "Open iPhone Development"라는 책에서 주제에 대한 토론을 보았지만 여전히 이해가되지 않습니다.


때로는 상속이 가치가있는 것보다 더 많은 문제처럼 보입니다. 해당 클래스의 동작을 변경 한 기존 클래스에 무언가를 추가하려는 경우 올바르게 사용됩니다.

범주를 사용하면 기존 개체가 조금 더 많은 작업을 수행하기를 원합니다. 이미 주어진 것처럼 압축을 처리하는 문자열 클래스 만 갖고 싶다면 문자열 클래스를 하위 클래스화할 필요가 없으며 압축을 처리하는 범주를 생성하기 만하면됩니다. 이렇게하면 이미 사용중인 문자열 클래스의 유형을 변경할 필요가 없습니다.

단서는 범주가 메서드 만 추가한다는 제한에 있습니다. 범주를 사용하여 클래스에 변수를 추가 할 수 없습니다. 클래스에 더 많은 속성이 필요하면 하위 클래스로 분류해야합니다 (편집 : 연관 저장소를 사용할 수 있다고 생각합니다).

카테고리는 기능을 추가하는 동시에 상속보다 합성을 선호하는 객체 지향 원칙을 준수하는 좋은 방법입니다.

2012 년 1 월 수정

지금 상황이 바뀌 었습니다. 현재 LLVM 컴파일러와 최신 64 비트 런타임을 사용하여 범주가 아닌 클래스 확장에 iVar 및 속성을 추가 할 수 있습니다 . 이렇게하면 공개 인터페이스에서 비공개 iVar를 유지할 수 있습니다. 그러나 iVar에 대한 속성을 선언하면 Objective-C에는 여전히 private 메서드와 같은 것이 없기 때문에 KVC를 통해 액세스 / 변경할 수 있습니다.


카테고리를 사용하면 기존 클래스에 메소드를 추가 할 수 있습니다. 따라서 펑키 한 새 암호화 방법을 추가하기 위해 NSData를 하위 클래스로 지정하는 대신 NSData 클래스에 직접 추가 할 수 있습니다. 이제 앱의 모든 NSData 개체가 해당 메서드에 액세스 할 수 있습니다.

이것이 얼마나 유용한 지 보려면 다음을보십시오 : CocoaDev


Objective-c 카테고리의 가장 좋아하는 삽화 중 하나는 NSString입니다. NSString은 뷰나 창에 대한 개념이없는 Foundation 프레임 워크에 정의되어 있습니다. 그러나 Cocoa 애플리케이션에서 NSString을 사용하면 – drawInRect:withAttributes:.

AppKit은 추가 그리기 방법을 제공하는 NSString에 대한 범주를 정의합니다. 카테고리는 기존 클래스에 새 메소드를 추가 할 수 있도록 허용하므로 NSStrings 만 다루고 있습니다. AppKit이 대신 하위 클래스로 그리기를 구현했다면 'AppKitStrings'또는 'NSSDrawableStrings'또는 이와 유사한 것을 처리해야합니다.

카테고리를 사용하면 기존 클래스에 애플리케이션 또는 도메인 별 메소드를 추가 할 수 있습니다. 매우 강력하고 편리 할 수 ​​있습니다.


프로그래머로서 코드 라이브러리 또는 애플리케이션에 대한 완전한 소스 코드 세트가 제공되면 해당 코드로 프로그래밍 목표를 달성하는 데 필요한 모든 것을 변경할 수 있습니다.

불행히도 이것은 항상 그런 것은 아니며 심지어 바람직한 것은 아닙니다. 많은 경우 바이너리 라이브러리 / 객체 키트와 함께 수행 할 헤더 세트가 제공됩니다.

그런 다음 몇 가지 작업을 수행 할 수 있도록 클래스에 새로운 기능이 필요합니다.

  1. 스톡 클래스 대신 새 클래스 전체를 만듭니다. 모든 함수와 멤버를 복제 한 다음 모든 코드를 다시 작성하여 새 클래스를 사용합니다.

  2. 스톡 클래스를 구성원 (합성)으로 포함하는 새 래퍼 클래스를 만들고 새 클래스를 활용하도록 코드베이스를 다시 작성합니다.

  3. 코드를 변경하기위한 라이브러리의 바이너리 패치 (행운)

  4. 컴파일러가 새 클래스를 이전 클래스로 보도록 강제하고 메모리 및 특정 진입 점의 특정 크기 또는 위치에 의존하지 않기를 바랍니다.

  5. 하위 클래스 전문화-기능을 추가하는 하위 클래스를 만들고 대신 하위 클래스를 사용하도록 드라이버 코드를 수정합니다. 이론적으로는 문제가 거의 없으며 데이터 멤버를 추가해야하는 경우 필요하지만 메모리 공간이 다릅니다. 하위 클래스에서 새 코드와 이전 코드를 모두 사용할 수 있고 사용할 코드, 기본 클래스 메서드 또는 재정의 된 메서드를 선택할 수있는 이점이 있습니다.

  6. 원하는 작업을 수행하거나 스톡 클래스의 이전 메서드를 재정의하는 메서드가 포함 된 범주 정의로 필요한 objc 클래스를 수정합니다.

    또한 라이브러리의 오류를 수정하거나 새 하드웨어 장치 등에 대한 방법을 사용자 지정할 수 있습니다. 만병 통치약은 아니지만 변경되지 않은 클래스 / 라이브러리를 다시 컴파일하지 않고도 클래스 메서드를 추가 할 수 있습니다. 원래 클래스는 코드, 메모리 크기 및 진입 점에서 동일하므로 레거시 앱이 중단되지 않습니다. 컴파일러는 단순히 새 메서드를 해당 클래스에 속하는 것으로 런타임에 넣고 원본 코드와 동일한 서명을 사용하여 메서드를 재정의합니다.

    예 :

    직렬 포트가 아닌 터미널로 출력하는 Bing 클래스가 있으며 이제 이것이 필요한 것입니다. (몇 가지 이유). Bing.h 및 libBing.so가 있지만 키트에 Bing.m이 없습니다.

    Bing 클래스는 내부적으로 모든 종류의 작업을 수행합니다. 사용자는 모든 것을 알지 못하며 헤더에 공용 API 만 있습니다.

    당신은 똑똑하기 때문에 Bing 클래스에 대한 (SerialOutput) 범주를 만듭니다.

    [Bing_SerialOutput.m]
    @interface Bing (SerialOutput)   // a category
    - (void)ToSerial: (SerialPort*) port ;
    @end
    
    @implementation Bing (SerialOutput)
    - (void)ToSerial: (SerialPort*) port 
    {
    ... /// serial output code ///
    }
    @end
    

    컴파일러는 앱과 연결할 수있는 개체를 만들어야하며 이제 런타임은 Bing이 @selector (ToSerial :)에 응답한다는 것을 알고 있으며 Bing 클래스가 해당 메서드로 빌드 된 것처럼 사용할 수 있습니다. 데이터 멤버 전용 메서드를 추가 할 수 없으며 이는 기본 클래스에 연결된 거대한 코드 종양을 생성하기위한 것이 아니지만 엄격하게 형식화 된 언어에 비해 장점이 있습니다.


이 답변 중 일부는 상속이 기존 클래스에 기능을 추가하는 더 무거운 방법 인 반면 카테고리는 더 가볍다는 생각을 적어도 지적한다고 생각합니다.

상속은 새로운 클래스 계층 구조 (모든 종소리와 휘파람)를 만들 때 사용되며 기존 클래스에 기능을 추가하는 방법으로 선택되면 많은 작업을 가져올 수 있습니다.

As someone else here put it... If you are using inheritance to add a new method for example to NSString, you have to go and change the type you're using in any other code where you want to use this new method. If, however, you use categories, you can simply call the method on existing NSString types, without subclassing.

The same ends can be achieved with either, but categories seem to give us an option that is simpler and requires less maintenance (probably).

Anyone know if there are situations where categories are absolutely necessary?


A Category is like a mixin: a module in Ruby, or somewhat like an interface in Java. You can think of it as "naked methods". When you add a Category, you're adding methods to the class. The Wikipedia article has good stuff.


The best way to look at this difference is that: 1. inheritance : when want to turn it exactly in your way. example : AsyncImageView to implement lazy loading. Which is done by inheriting UIView. 2. category : Just want to add a extra flavor to it. example : We want to replace all spaces from a textfield's text

   @interface UITextField(setText)
      - (NSString *)replaceEscape;
   @end

   @implementation UITextField(setText)
      - (NSString *)replaceEscape
      {
         self.text=[self.text stringByTrimmingCharactersInSet:
                           [NSCharacterSet whitespaceCharacterSet]];
         return self.text;
      }
   @end

--- It will add a new property to textfield for you to escape all white spaces. Just like adding a new dimension to it without completely changing its way.

ReferenceURL : https://stackoverflow.com/questions/522341/what-is-the-difference-between-inheritance-and-categories-in-objective-c

반응형