在运行时检查协议继承

时间:2017-11-07 21:34:01

标签: swift reflection swift-protocols

在运行时检查类型的协议一致性很容易:

guard type is Encodable.Type else { ... }

但如果type不是structclass,而是protocol继承自Encodable,则此技术会失败。有没有办法对协议进行类似的检查?

1 个答案:

答案 0 :(得分:1)

这有点讨厌,但它可能会解决你的问题:

给出以下示例类型:

import { Platform}                                    from "@angular/cdk/platform";
import { Directive, ElementRef, Optional, Renderer2 } from "@angular/core";
import { FormGroupDirective, NgControl, NgForm }      from "@angular/forms";
import { ErrorStateMatcher, MatInput}                 from "@angular/material";

import { ReactorService }                             from "./thrc-react.service";

@Directive({
  selector: `input[responsiveMatInput], textarea[responsiveMatInput]`,
  exportAs: 'responsiveMatInput',
  host: {
    'class': 'mat-input-element mat-form-field-autofill-control',
    // Native input properties that are overwritten by Angular inputs need to be synced with
    // the native input element. Otherwise property bindings for those don't work.
    '[attr.id]': 'id',
    '[placeholder]': 'placeholder',
    '[disabled]': 'disabled',
    '[required]': 'required',
    '[readonly]': 'readonly',
    '[attr.aria-describedby]': '_ariaDescribedby || null',
    '[attr.aria-invalid]': 'errorState',
    '(blur)': '_focusChanged(false)',
    '(focus)': '_focusChanged(true)',
    '(input)': '_onInput()',
  },
})
export class ResponsiveInputComponent extends MatInput {
  constructor(protected _elementRef: ElementRef,
              protected _renderer: Renderer2,
              protected _platform: Platform,
              @Optional() public ngControl: NgControl,
              @Optional() protected _parentForm: NgForm,
              @Optional() protected _parentFormGroup: FormGroupDirective,
              _defaultErrorStateMatcher: ErrorStateMatcher,
              reactor: ReactorService, // My service, in case it weren't obvious.
  ) {
    super(_elementRef, _renderer, _platform, ngControl,_parentForm,
      _parentFormGroup, _defaultErrorStateMatcher);
    reactor.reactor$.subscribe(event => {
        console.log('Received.', event);
        // My custom code...
      }
    );

  }
}

我通过假设:

来简化示例的init逻辑
protocol Animal: Encodable {}

struct Person: Animal {}

protocol SomeOtherProtocol {}

struct Demon: SomeOtherProtocol {}

这适用于自定义集合类但是...继续,为自定义集合定义以下扩展名

typealias Group = Array
let animals: Group<Animal> = [Person(), Person(), Person()]
let notAnimals: Group<SomeOtherProtocol> = [Demon(), Demon(), Demon()]

您现在可以访问以下内容:

extension Group {
    func asEncodables() -> Group<Encodable>?{
        return self as? Group<Encodable>
    }

    var isElementEncodable: Bool {
        return self is Group<Encodable>
    }
}

因此,对于您的原始问题,您可以按如下方式进行检查:

animals.asEncodables() //returns some
notAnimals.asEncodables() // returns none

animals.isElementEncodable //true
notAnimals.isElementEncodable //false

希望这会对你有所帮助。目前我知道无法与类似guard notAnimals.isElementEncodable else { return } :/

的内容进行比较