Swift 네이티브 기본 클래스 또는 NSObject


105

Swift로 몇 가지 isa를 테스트 한 결과 NSObject가 수퍼 클래스 (직접 또는 더 높은 수준)이거나 '@objc'장식을 사용하는 경우에만 작동한다는 것을 발견했습니다. 그렇지 않으면 C ++와 같은 static- 및 vtable-dispatch 스타일을 따릅니다.

Cocoa / NSObject 기본 클래스없이 Swift 클래스를 정의하는 것이 정상입니까? 내가 염려된다면 이것은 메소드 인터 셉션 및 런타임 인트로 스펙 션과 같은 Objective-C의 역 동성을 훨씬 앞선 것을 의미합니다.

동적 런타임 동작은 속성 관찰자, 핵심 데이터, 측면 지향 프로그래밍 , 고차원 메시징 , 분석 및 로깅 프레임 워크 등과 같은 기능의 핵심 입니다.

Objective-C의 메서드 호출 스타일을 사용하면 메서드 호출에 약 20 개의 기계 코드 피연산자가 추가되므로 특정 상황에서 ( 작은 본문이있는 메서드에 대한 많은 엄격한 호출 ) C ++ 스타일 정적 및 vtable 디스패치가 더 잘 수행 될 수 있습니다.

그러나 일반적인 95-5 규칙 ( 95 %의 성능 향상은 코드의 5 % 조정에서 비롯됨)을 고려할 때 강력한 동적 기능으로 시작하여 필요한 경우 강화하는 것이 합리적이지 않습니까?


관련 : Swift는 측면 지향 프로그래밍을 지원합니까? stackoverflow.com/a/24137487/404201
Jasper Blues

답변:


109

NSObject의 하위 클래스 인 Swift 클래스 :

  • Objective-C 클래스 자체입니다.
  • objc_msgSend()(대부분의) 메서드 호출에 사용
  • 메서드 구현 (대부분)에 대한 Objective-C 런타임 메타 데이터 제공

NSObject의 하위 클래스가 아닌 Swift 클래스 :

  • Objective-C 클래스이지만 NSObject 호환성을 위해 몇 가지 메소드 만 구현합니다.
  • objc_msgSend()메서드 호출에 사용하지 마십시오 (기본값).
  • 메서드 구현에 대한 Objective-C 런타임 메타 데이터를 제공하지 않습니다 (기본값).

Swift에서 NSObject를 서브 클래 싱하면 Objective-C 런타임 유연성은 물론 Objective-C 성능도 얻을 수 있습니다. Objective-C의 유연성이 필요하지 않은 경우 NSObject를 피하면 성능이 향상 될 수 있습니다.

편집하다:

Xcode 6 베타 6에서는 동적 속성이 나타납니다. 이를 통해 메서드가 동적 디스패치를 ​​사용해야하며 따라서 가로 채기를 지원하도록 Swift에 지시 할 수 있습니다.

public dynamic func foobar() -> AnyObject {
}

1
Swift는 objc_msgSend 대신 어떤 종류의 디스패치를 ​​사용합니까? 정적입니까?
Bill

12
Swift는 objc_msgSend 디스패치, 가상 테이블 디스패치, 직접 디스패치 또는 인라인을 사용할 수 있습니다.
Greg Parker

정적 : 1.1ns 미만. vtable 1.1ns, msgSend 4.9ns. . (물론 하드웨어에 따라 다름). . '순수한'스위프트가 시스템 수준 프로그래밍을위한 훌륭한 언어를 만드는 것 같지만, 앱의 경우 동적 기능을 포기하는 것을 꺼릴 것입니다.하지만 가비지 컬렉션 대 ARC에서 컴파일러로 이동하면 기쁩니다. . . 정적 디스패치가 멀티 코어 시스템에서 더 나은 분기 예측 (따라서 성능)을 허용한다고 들었습니다. 진실?
Jasper Blues

"NSObject의 하위 클래스가 아닌 스위프트 클래스는 Objective-C 클래스입니다."-해당 위치에 대한 링크를 제공 할 수 있습니까?
Matt S.

1
요약하면 Objective C 코드와 통신해야하는 경우 Swift에서 NSObject 만 하위 클래스로 만들어야합니까?
MobileMon

14

또한 NSObject에 Swift 클래스를 기반으로하면 코딩 버그를 숨길 수있는 예기치 않은 런타임 동작을 발견했습니다. 여기에 예가 있습니다.

NSObject를 기반으로 하지 않는 이 예제 에서 컴파일러는 testIncorrect_CompilerShouldSpot에서 오류를 올바르게 발견하여 "... 'MyClass'는 'MirrorDisposition'으로 변환 할 수 없습니다."라고보고합니다.

class MyClass {
  let mString = "Test"

  func getAsString() -> String {
    return mString
  }

  func testIncorrect_CompilerShouldSpot() {
    var myString = "Compare to me"
      var myObject = MyClass()
      if (myObject == myString) {
        // Do something
      }
  }

  func testCorrect_CorrectlyWritten() {
    var myString = "Compare to me"
      var myObject = MyClass()
      if (myObject.getAsString() == myString) {
        // Do something
      }
  }
}

NSObject를 기반으로하는이 예제 에서 컴파일러 testIncorrect_CompilerShouldSpot에서 오류를 발견 하지 않습니다 .

class myClass : NSObject {
  let mString = "Test"

  func getAsString() -> String {
    return mString
  }

  func testIncorrect_CompilerShouldSpot() {
    var myString = "Compare to me"
      var myObject = MyClass()
      if (myObject == myString) {
        // Do something
      }
  }

  func testCorrect_CorrectlyWritten() {
    var myString = "Compare to me"
      var myObject = MyClass()
      if (myObject.getAsString() == myString) {
        // Do something
      }
  }
}

도덕적 인 것은 당신이 정말로 해야하는 NSObject에만 기반한다는 것입니다!


1
정보 주셔서 감사합니다.
Jasper Blues

13

언어 참조에 따르면 클래스가 표준 루트 클래스를 하위 클래스로 분류하기위한 요구 사항이 없으므로 필요에 따라 수퍼 클래스를 포함하거나 생략 할 수 있습니다.

클래스 선언에서 슈퍼 클래스를 생략해도 어떤 종류의 암시 적 기본 슈퍼 클래스도 할당되지 않습니다. 독립적 인 클래스 계층 구조의 루트가되는 기본 클래스를 정의합니다.

언어 참조에서 :

Swift 클래스는 범용 기본 클래스에서 상속되지 않습니다. 수퍼 클래스를 지정하지 않고 정의한 클래스는 자동으로 빌드 할 기본 클래스가됩니다.

super수퍼 클래스가없는 클래스 (즉, 기본 클래스)에서 참조하려고 하면 컴파일 시간 오류가 발생합니다.

'super' members cannot be referenced in a root class

1
네. 프로젝트 컨텍스트에서 Cocoa 또는 Cocoa Touch 소스 파일을 만들려고하면 하위 클래스를 삽입하는 양식이 실제로는 공백으로 두면서 클래스를 만들지 못하게합니다. 수퍼 클래스가 생성되면 나중에 제거 할 수 있습니다.
Cezar

1
감사. 정적 및 vtable 디스패치를 ​​사용하는 것은 시스템 프로그래밍 또는 성능 조정에 적합합니다. 네이티브 Cocoa와의 일관성을 위해 동적 기본값 이어야 한다고 생각 합니다 . (누군가가 저를 다르게 설득 할 수 없다면,이 질문입니다).
Jasper Blues

1

저는 스위프트 데이터의 대부분이 objc. Objective C 인프라와 통신해야하는 부분 만 명시 적으로 표시됩니다.

런타임 인트로 스펙 션이 언어에 어느 정도 추가 될지는 모르겠습니다. 메서드 차단은 메서드가 명시 적으로 허용하는 경우에만 가능합니다. 이것은 내 생각이지만, 애플 내의 언어 디자이너들만이 그들이 정말로 어디로 가고 있는지 정말로 알고 있습니다.


나에게는 역 동성을 기본값으로 만드는 것이 합리적입니다 ( '@objc'장식 또는 다른 접근 방식을 사용하여 NSObject 확장을 통해). 기본 클래스가 없을 때 Swift는 더 나은 성능을 제공하는 static / vtable 디스패치를 ​​선호하지만 대부분의 경우 필요하지 않습니다. . (90 %의 이득은 코드의 10 %를 조정하여 발생합니다). 제 희망은 Objective-C의 역동 성과 일관성이 옵트 인이 아니라 옵트 아웃이라는 것입니다.
Jasper Blues

언어가 디자인 된 방식은 선택 사항입니다. 우리가 아는 한 미래에는 기본적으로 objc가 아닌 시스템 API가 추가 될 것입니다. 중장기 적으로 그들은 non-objc 코드를 호출하는 objc의 얇은 호환성 레이어를 사용하여 기존 라이브러리를 non-objc 코드로 마이그레이션 할 수도 있습니다. 우리는 모릅니다. 우리는 아마 educated guesses지금부터 몇 년 안에 만들 수있을 것입니다 . 그러나 현재로서는 큰 물음표 일뿐입니다.
Analog File

@JasperBlues 나는 대부분의 경우 역 동성이 필요하지 않다고 주장하고 기본적으로 성능을 선호하고 동적 행동을 선택해야합니다. :) 각각 자신의 I의 추측
랜스

@ 랜스 흠. 아마도. 저는 여전히 관찰자, AOP, 테스트 모의 프레임 워크, 분석 프레임 워크 등에 대해 걱정하고 있습니다. 성능에 대한 문제는 이득의 90 %가 10 % 튜닝에서 나온다는 것입니다. . 그게 내 근거입니다. 10 % 사례를 선택하는 것입니다. AOP는 iOS 엔터프라이즈 앱에서 큰 문제가 될 것이라고 생각하지만 C ++ 에서처럼 컴파일러 도구를 사용하여 수행 할 수 있습니다. . 확실히 게임, 과학 컴퓨팅, 그래픽 등의 devs :) 더 높은 성능을 환영합니다
재스퍼 블루스

1

다음은 Apple의 Swift-eBook에서 복사되었으며 질문에 대한 적절한 답변을 제공합니다.

기본 클래스 정의

다른 클래스에서 상속하지 않는 모든 클래스를 기본 클래스라고합니다.

Swift 클래스는 범용 기본 클래스에서 상속되지 않습니다. 수퍼 클래스를 지정하지 않고 정의한 클래스는 자동으로 빌드 할 기본 클래스가됩니다.


참고

https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Inheritance.html#//apple_ref/doc/uid/TP40014097-CH17-XID_251


-6

보통이다. Swift의 디자인 목표를보십시오. 목표는 방대한 종류의 프로그래밍 문제를 없애는 것입니다. 메소드 재구성은 아마도 스위프트로하고 싶은 일 중 하나가 아닐 것입니다.


3
메서드 재구성은 런타임에 가로 채기 패턴을 달성하는 방법입니다. 이를위한 용도 중 하나는 Aspect Oriented Programming의 원칙에 따라 교차 절단 문제를 적용하는 것입니다. Apple의 자체 알림, 속성 관찰자 (Swift에 내장), 핵심 데이터는 모두 스위 즐링을 사용하여 좋은 효과를냅니다. . 어설픈 구문에도 불구하고 Objective-C에 사람들을 매료시킨 것 중 하나는 이러한 역 동성으로 인터셉트 패턴이 필요할 때마다 우아한 솔루션을 쉽게 제공 할 수 있습니다. . 사실 Objc에 대한 공식적인 AOP 프레임 워크는 없었습니다. 원자재가 너무 좋았 기 때문입니다.
Jasper Blues

이것이 지금 끝났다는 사실이 그것이 내일 어떻게 될 것인지를 의미하지는 않습니다. 알림을 말했듯이 속성 관찰자, 델리게이트 및 이와 유사한 것은 기본적으로 제공되거나 제공 될 수 있습니다. 언어는 진화 할 것이며 우리는 어느 방향으로 나아가는지 모릅니다. 함수형 프로그래밍에 대한 지원 측면 에서 많은 것을 얻었습니다 . 그러나 그것은 비정상적인 방식으로 그것을 수행하므로 얼마나 많은 것이 누락되었는지 전혀 모릅니다. 그러나 우리가 아는 한 그들은 돌연변이를 억제하고 순수 함수형 프로그래밍을 장려하는 방향으로 향하고있을 수 있습니다. UI의 미래가 반응 형이라면 어떨까요? 아직 알 방법이 없습니다.
Analog File

1
예, 그러나 이러한 모든 작업은 인터 셉션에 의존하며 컴파일 타임 (C ++) 또는 런타임 (Ruby, Objective-C, Java (asm, cglib, ApsectJ 등을 통해))의 두 가지 방법을 수행 할 수 있습니다. 현대 언어는 런타임에이를 수행하는 경향이 있습니다. 사람들은 Objective-C를 좋아했습니다. 오래된 코저 임에도 불구하고 현대 언어처럼 행동했기 때문입니다. 당신이 말했듯이, 언어에 구워진 것이 많을수록 더 좋습니다 (잘 수행 되었다면!). . 하지만 지금 은 Objc / Foundation이 제공하는 레거시에 연결할 수 있습니다. 이것이 NSObject 확장이 향후 몇 년 동안 일상적인 앱의 표준 관행이되기를 바라는 이유입니다.
Jasper Blues
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.