iOS开发之泛型使用
<h4 class="p1"><span class="s2">1. 泛型:限制类型<br></span></h4><ul>
<li class="p1">
<p><strong><span class="s2">1.1.泛型使用场景<span class="s2">:</span></span></strong></p>
<ul>
<li class="p1">
<p>1.<span class="s1">在集合(<span class="s1">数组NSArray<span class="s1">、字典NSDictionary<span class="s1">、集合NSSet)<span class="s1">中使用泛型比较常见。</span></span></span></span></span></p>
</li>
<li class="p1">
<p><span class="s2">2.当声明一个类,但是类里面的某些属性的类型不确定的时候,我们才使用泛型。</span></p>
</li>
</ul>
</li>
<li class="p2"><strong><span class="s2">1.2.泛型书写规范</span></strong></li>
</ul>
<p class="p1"><span class="s1"> 在类型后面定义泛型:NSMutableArray<UITouch *> dataArray</span> </p>
<ul>
<li class="p2"><strong><span class="s2">1.3.泛型修饰</span></strong></li>
</ul>
<p class="p2"> 只能修饰方法的调用。 </p>
<ul>
<li class="p2"><strong><span class="s2">1.4.泛型好处<span class="s2">:</span></span> </strong></li>
</ul>
<p class="p2"> <span class="s2">1.提高开发的规范,减少程序员之间的交流。</span></p>
<p class="p2"> <span class="s2">2.通过集合取出来的对象,可以直接当做泛型对象使用。这样我们就可以直接使用<span class="s2">.点语法。</span></span></p>
<h4 class="p2"><span class="s2">2.代码使用泛型:</span></h4>
<ul>
<li class="p1">
<p><span class="s1"><strong>2.1.</strong><span class="s1"><strong>声明一个泛型为NSString</strong><span class="s1"><strong>的数组</strong><br></span></span></span>具体做法就是在 NSMutableArray <span class="s1"><span class="s1">后带一个 <NSString *> <span class="s1">,尖括号内部即为泛型类型<br></span></span></span></p>
<div class="cnblogs_code">
<pre>@property (nonatomic, strong, nullable) NSMutableArray<NSString *> *dataArray;</pre>
</div>
</li>
</ul>
<ul>
<li class="p2"><span class="s2">2.2.当我们要给数组添加对象或取出对象的时候,系统就会自动提示应该传入或者取出来的对象的类型,这个类型就是你刚才声明的泛型类型</span>
<ul>
<li class="p1"><span class="Apple-converted-space"><span class="Apple-converted-space"><span class="Apple-converted-space"><span class="s1">没有使用泛型<br></span></span></span></span>
<div class="cnblogs_code">
<pre>;</pre>
</div>
</li>
<li class="p1"><span class="Apple-converted-space"><span class="Apple-converted-space"><span class="Apple-converted-space"><span class="s1">使用泛型<br></span></span></span></span>
<div class="cnblogs_code">
<pre> ;</pre>
</div>
</li>
<li class="p1">
<p><span class="Apple-converted-space">添加不正确的类型,会出现警告<br></span></p>
<div class="cnblogs_code">
<pre> ;</pre>
</div>
</li>
<li class="p2">
<p class="p1">我们可以直接将集合中取出来的对象当做泛型使用</p>
<div class="cnblogs_code">
<pre>NSInteger length = ;</pre>
</div>
</li>
<li class="p2">代码如下<br><img src="https://img2020.cnblogs.com/blog/1115039/202003/1115039-20200317165652707-297021822.png"> </li>
</ul>
</li>
</ul>
<h4 class="p2"><span class="s2">3.泛型的自定义</span></h4>
<p class="p2"> 刚才我们只是实现了系统类<span class="s2">NSMutableArray的泛型。接下来我们要考虑下,我们怎么样在我们自己的类中声明一个泛型的属性呢?</span></p>
<p class="p2"> 为了这个目的,我们创建一个<span class="s2"> Language 的类表示<span class="s2"> “语言”。并且创建两个<span class="s2"> Language 的子类,分别叫<span class="s2"> Java 和<span class="s2"> IOS 。很明显这两个是“某一个类型的语言”。我们创建一个<span class="s2">Person的类,给类声明一个泛型,在类的<span class="s2"> .h 文件中声明一个声明一个属性,这个属性表示这个人会的语言,即为<span class="s2"> IOS 或者<span class="s2"> Java 。那么我们有以下两种声明方式: </span></span></span></span></span></span></span></span></span></p>
<ul>
<li class="p1"><strong>id:</strong><span class="s1"><span class="s1"><strong>任何对象都能传进来</strong><br></span></span>
<div class="cnblogs_code">
<pre>@property (nonatomic, strong, null_unspecified) id language;</pre>
</div>
</li>
<li class="p2"><span class="s2"><span class="s2"><strong> Language:在外面调用的时候不能提示具体是哪种语言</strong><br></span></span>
<div class="cnblogs_code">
<pre>@property (nonatomic, strong, null_unspecified) Language *language;</pre>
</div>
</li>
<li class="p2"><strong>代码示例:</strong><br>
<div class="cnblogs_code">
<pre>#import <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Language.h</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
NS_ASSUME_NONNULL_BEGIN
@interface Person : Language
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*! 第一种方式</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
@property (nonatomic,strong,null_unspecified) id languageOne;
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*! 第二种方式</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
@property (nonatomic,strong,null_unspecified) Language </span>*<span style="color: rgba(0, 0, 0, 1)">languageTwo;
@end
NS_ASSUME_NONNULL_END</span></pre>
</div>
</li>
</ul>
<p class="p2"> 因为<span class="s2"> Language 这个语言并不能代表这个<span class="s2"> Person 究竟会什么语言,我们需要的属性时<span class="s2"> IOS 和<span class="s2"> Java。这两种都可以在调用的时候传入<span class="s2"> Java 和<span class="s2"> IOS 两种对象,但它们的缺点也非常明显,若使用<span class="s2"> id 则我们可以传入任何对象,而不只是<span class="s2"> Java 和<span class="s2"> IOS ;使用<span class="s2"> Language * 呢,我们没有办法在编译的时候确定这个人究竟会什么语言,而只能在运行时判断。有没有办法让我们在编译的时候就能知道<span class="s2"> Person 具体会哪种<span class="s2"> Language 呢?</span></span></span></span></span></span></span></span></span></span></span></span></p>
<p class="p2"> 办法就是泛型。</p>
<p class="p2"> 声明自定义类的泛型,我们需要做这样一步:</p>
<ul>
<li class="p2"><span class="s2"><span class="s2">(给类<span class="s2">)声明一个泛型<br></span></span></span>
<div class="cnblogs_code">
<pre>@interface JTPerson<ObjectType> : NSObject</pre>
</div>
<p class="p2">看出区别了吗?我们在<span class="s2"> interface 类名之后加了一对尖括号<span class="s2"> <> ,中间是<span class="s2"> ObjectType 。这个就代表泛型。这样我们在声明属性的时候就可以这么写: </span></span></span></p>
<div class="cnblogs_code">
<pre>@property (nonatomic, strong, null_unspecified) ObjectType language;</pre>
</div>
<p class="p2">也就是,我们现在不指定具体的类型,而在实例化这个类的时候确定这个泛型。若不确定,那么所有的<span class="s2"> ObjectType 会自动变成<span class="s2"> id 。<br>像这样:<br></span></span></p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> iOS</span>
JTPerson<IOS *> *iOSP =<span style="color: rgba(0, 0, 0, 1)"> [ init];
</span><span style="color: rgba(0, 128, 0, 1)"> // </span><span style="color: rgba(0, 128, 0, 1)">;</span>
<span style="color: rgba(0, 128, 0, 1)"> // </span><span style="color: rgba(0, 128, 0, 1)">;</span>
<span style="color: rgba(0, 128, 0, 1)"> // </span><span style="color: rgba(0, 128, 0, 1)"> init]];</span><span style="color: rgba(0, 128, 0, 1)"><br></span></pre>
<pre><span style="color: rgba(0, 128, 0, 1)"> //</span><span style="color: rgba(0, 128, 0, 1)"> Java</span>
JTPerson<Java *> *javaP =<span style="color: rgba(0, 0, 0, 1)"> [ init];
</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ;</span>
<span style="color: rgba(0, 128, 0, 1)"> //</span><span style="color: rgba(0, 128, 0, 1)"> ;</span>
<span style="color: rgba(0, 128, 0, 1)"> //</span><span style="color: rgba(0, 128, 0, 1)"> init]];</span></pre>
</div>
<p class="p2">这样,我们在声明<span class="s2"> Person这个类的时候,就顺便声明了这个类的泛型。这样系统就会在你使用到泛型的属性与方法的时候,自动提醒你声明的泛型类型了。</span></p>
<p class="p3"><img src="https://img2020.cnblogs.com/blog/1115039/202003/1115039-20200317171648432-427872027.png"> </p>
</li>
</ul>
<h4 class="p2"><span class="s2">4. 泛型的协变与逆变</span> </h4>
<p> 下图是系统<span class="s1"> NSArray 的头文件部分,可以看到它使用了自定义泛型并命名为<span class="s1"> OBjectType,</span></span></p>
<p> 在自定义泛型前加了一个<span class="s1"> __covariant 的修饰符,这个修饰符就表示协变性<br><br><img src="https://img2020.cnblogs.com/blog/1115039/202003/1115039-20200317172438518-531839233.png"><br></span></p>
<p> </p>
<ul>
<li class="p1"><span class="s1">__covariant - 协变性,子类型可以强转到父类型(里氏替换原则)</span></li>
<li class="p2">__contravariant - <span class="s2">逆变性,父类型可以强转到子类型</span></li>
</ul><br><br>
来源:https://www.cnblogs.com/lxlx1798/p/11642938.html
頁:
[1]