Objective-C переопределяет параметр _Nullable с параметром _Nonnull - PullRequest
0 голосов
/ 14 мая 2018

Почему этот код генерирует следующее предупреждение?

@interface Foo : NSObject 
- (void)m:(id _Nullable)p;
@end

@interface Bar : Foo
- (void)m:(id _Nonnull)p;
@end

конфликтующий спецификатор обнуляемости для типов параметров, '_Nonnull' конфликтует с существующим спецификатором '_Nullable' [-Wnullability]

Но другойспособ не генерирует предупреждения:

@interface Foo : NSObject 
- (void)m:(id _Nonnull)p;
@end

@interface Bar : Foo
- (void)m:(id _Nullable)p;
@end

Это потому, что во втором случае мы идем от более ограничительного к менее ограничительному?

1 Ответ

0 голосов
/ 20 мая 2018

Это все из-за принципа замены Лискова

Согласно этому принципу:

, если S является подтипом T,тогда объекты типа T могут быть заменены объектами типа S. без изменения каких-либо желательных свойств программы.


В вашем примере: Bar является подтипом Foo.Таким образом, вы должны иметь возможность заменить экземпляр Foo на экземпляр Bar.

Другими словами, представьте метод

- (void)doSomethingWith:(Foo *)object {
    [object m:nil];
}

Если вы передадите этому методу экземпляр Foo - все отлично.Но вы не можете передать ему экземпляр Bar - потому что вы не можете вызвать [Bar m:nil]

Здесь вы можете видеть, что этот код нарушает принцип подстановки Лискова.


В противном случае во втором примере все в порядке.

Представьте себе метод:

- (void)doSomethingWith:(Foo *)object {
    [object m:@""]; // _Nonnull requirement
}

Как видите, вы можете перейти к экземплярам этого методаклассов Foo и Bar.


ПРИМЕЧАНИЕ: Здесь важно отметить, что в Objc (в отличие от Swift) эти правила не так строги, и вы можетелегко обмануть компилятор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...