黑马程序员--07 OC 三大特性

                                 ------ Java培训、Android培训、iOS培训、.Net培训 、期待与您交流! -------



三大特性:封装,继承,多态


#封装 #


 @public的成员可以被任意赋值,这样数据通过 指针->成员变量名 方式给成员变量赋值,可能被赋值为不合理的数值具有危险性。通过封装后便可解决上述问题,封装的好处:过滤不合理的值,保证数据的安全性; 屏蔽内部的赋值过程;让外界不必关注内部的细节


不使用@public后,便不能通过指针->成员变量名 的方式给成员变量赋值 (被保护)。要通过调用方法来设置成员变量的值。 

设置成员变量属性值的方法通常称为该属性的set方法

set方法:

 作用:提供一个方法给外界设置成员变量的值,可以在方法里面对参数进行相应的过滤。

 set方法命名规范: a.方法名必须以set开始

b. set后面跟上成员变量名称,其首字母必须大写

 c.返回值一定是void

 d.一定要接收一个参数,而且参数类型和成员变量类型一致

   e.形参名称不能和成员变量名称一样

                         - (void) setWheels: (int)wheels;


没有@public, 我们就不能通过 指针->成员变量名  来查看成员变量的值 (被保护). 我们要通过调用方法来返回成员变量值

获取成员变量值得方法,通常称为get方法。

get方法:

 作用:返回对象内部的成员变量

 get方法命名规范

a.肯定有返回值,返回值类型和成员变量类型一致

b.方法名与一般与成员变量名一样(不以get开头;不加下划线)

c.不需要接收任何参数

- (int) wheels;


成员变量命名规范

a.一定要以下划线开头

作用:a.让成员变量与get方法区分开

b.可以与局部变量区分开,一看到下划线开头的变量一般是成员变量


#import <Foundation/Foundation.h>

@interface Student : NSObject
{
    int _age;
}

- (void)setAge:(int)Myage;
- (int)age;

@end

@implementation Student

- (void)setAge:(int)Myage
{
    _age = Myage;
}

- (int)age
{
    return _age;
}

@end

int main()
{
    Student *p = [Student new];
    
    [p setAge:10];
    
    NSLog(@"p=%d",[p age]);
    
    return 0;
}



#继承#

继承的含义

 B继承了类A,那么类B具有类A的所有属性和方法.

 OC中继承关系用 :表示.

继承的好处:

a.抽取重复代码

b.建立类之间的关系

c.子类可以拥有父类的所有成员变量和方法

e.不改变原来模型的基础上,拓充方法

缺点:耦合性太强


细节:OC是单继承,每个类只能继承一个父类,不能继承多个

NSObject是基类,几乎所有的类最终都是继承于它.也有的类不是继承NSObject,比如NSProxy,它也是      一个基类.我们常用NSObject.

父类\超类 superclass  子类 subclass\subclasses

 子类有自己的成员变量方法,和父类的所有成员变量和方法 (以及父类的父类的).

#子类对父类的重写#



父类必须声明在子类的前面. 实现可以放在后面.和函数一样.

子类不可以再定义和父类同名的成员变量.

子类可以再定义和父类同名的方法.称为重写方法. 子类的对象调用方法时,系统会先在子类的方法定义中寻找方法,如果没有,再到父类中寻找.如果没有,再到父类的父类中寻找。

类方法和对象方法一样的寻找方式, 也可以重写.

 
@interface Person : NSObject
{
        int _age;
}
- (void) run;
@end
@implementation Person
@end
 
@interface Student : Person
{
        int _no;
        // int _age;   不可以和父类的成员变量重名
}
- (void) run;    // 可以覆盖重写父类的方法
@end
@implementation Student
@end



#类在内存中的存储 #

每个对象在内存中都有一个isa指针,指向类的空间 (里面包含类的方法的声明). 其实每个类里面也有一个指针,叫做superclass,指向它的父类 (包含父类的方法声明)

(其实是NSObject里有一个成员变量是 Class类型的 isa.所以每个类里面才有这个isa指针(使用typedef把星号隐藏了,是个指针,指向Class).可以打开NSObject的声明看一下) (superclass指针应该也是在NSObject. )

 

在程序运行前, 先把所有的类加载进内存.

每个类中都有自己的方法列表 (里面包含类的方法的声明).如果一个子类中没有声明/实现任何方法,那它的方法列表就是空的. (和属性不同,如果一个子类没有声明任何属性,它的对象的空间里还是有父类声明的属性)

每个类中都有一个指针, 指向自己的父类 (OC单继承). 当调用方法时,如果在自己的方法列表中没有对应的方法,就通过指针找到父类,在父类的方法列表中寻找对应的方法.

创建对象时,给每个对象开辟一块存储空间.这块空间中存放对象自己的成员变量 (包括父类声明的成员变量),以及一个isa指针 (NSObject声明的成员变量), isa指针指向它的类所在的空间.

当对象调用方法时, 通过isa指针找到类的方法列表,去调用方法.如果自己的类的方法列表中没有对应的方法,就通过类的superclass指针找到父类的方法列表,在那里再找对应的方法. 比如 [Student new]方法的调用过程.



#
继承与组合#

对象中有sia指向了类,类中有superclass指向了父类


继承的使用场合:a.当两个类拥有相同属性和方法时,可以把相同的部分抽取到父类中.

b.A类完全拥有B类中的部分属性和方法时可以考虑B继承A

比如:

A类含有属性 _age, _no

B类含有属性 _age, _no, _weight

可以考虑让B类继承A


但不是什么时候都可以这样用.

比如:狗有两个属性, 年龄和体重

人类有三个属性, 年龄,体重,身高.

但是不能让狗继承人. 语法上可以,但是逻辑上不合理.

这种情况不适用继承, 应该使用组合.让人拥有狗类型的成员变量,这样狗就是组成人的一部分.

@interface Person : NSObject {

        Dog *_dog;     // Dog对象

        int _height;

}

 

继承关系: BA         B : A   学生是人   Student : Person

组合关系: BA         B {属性A }   Student{Score *_score;........}

根据二者的逻辑关系选择.


继承的好处:

建立了两个类之间的关系;

抽取重复代码;

子类可以拥有父类所有的方法和成员变量

  

注意:

父类声明必须在子类前边,实现写在后边无所谓 

重写:子类实现父类中某个方法,覆盖父类以前的方法

子类不能拥有父类同样的成员变量

调用某个对象方法时候,优先在当前找,找不到了再去父类找

#self关键字的使用 #


self 是个指针,指向调用它的变量 (可能是类,也可能是对象).

self关键字不以@开头.

  使用self访问当前对象的成员变量 


@interface Person : NSObject
{
        int _age;
}
- (void) setAge:(int)age;
- (int) age;
- (void) printAge;
@end
                                            //在对象的方法里可以使用self关键字, self就指向调用这个方法的对象.
- (void) setAge:(int)age {
        self->_age = age;
}
//和 _age = age; 是等价的
 

#import <Foundation/Foundation.h>

@interface Dog : NSObject

- (void)bark;
- (void)run;
@end

@implementation Dog

- (void)bark
{
    NSLog(@"jiaoleyixia");
}

- (void)run
{
    [self bark]; // self在这里代表d
    NSLog(@"paoleyixia");
}

@end

int main()
{
    Dog *d = [Dog new];
    
    [d run];

    return 0;
}


使用场合:

如果方法里有一个局部变量和对象的成员变量是同名的, 那么使用_age调用的就是局部变量,但是使用self->_age就可以忽略局部变量,调用成员变量.

 

使用self调用方法 

a.self用在方法当中代表方法调用者, 谁调用这个方法, self就代表谁. 可以使用self来调用其它类方法或者对象方法.

b.对象方法中的self代表调用该方法的对象,所以只能调用其它对象方法,不能调用类方法.

c.类方法中的self只能调用其它类方法,不能调用对象方法,因为self代表调用该方法的类.

d.如果在方法内部调用这个方法本身,会造成递归,可能会导致无限循环.

e.self不能去调用函数,函数只能通过函数名(参数)方式调用,不可以通过self调用.

如:void haha() { ... }

这是函数, 就算是混在方法实现里也是函数,独立于类和对象存在.要通过函数调用的方式去调用.不要和方法混淆了.

 

总结

self的用途:用在方法中,谁调用这个方法, self就代表谁.

在对象方法中通过 self->_age 访问该对象的成员变量.

在对象方法中通过 [self test]调用对象方法.

在类方法中通过 [self test]调用类方法.




#super关键字的使用#


使用super关键字调用父类方法:

作用

a.直接调用父类的某一个方法

b.如果super处在对象方法中便调用父类的对象方法,.如果super处在类方法中便调用父类的类方法。

使用场合子类重写父类的方法时想保留父类原有的行为.




#多态#


前提: 没有继承就没有多态

含义:    子类的对象既可以用子类的指针指向,也可以用父类的指针指向.即对象可以具备多种形态,即父类指针指向子类对象。


假如有DogAnimal俩个类并且Dog继承Animal且拥有- (void) eat;方法     

 Animal *a = [Dog new]; //多态,即父类指针指向子类对象

  [a    eat];               //使用 [a eat] 调用方法时, 依然是a所指向的对象来调用相应的方法,所以即使aAnimal类型的指针,但是它指向的是Dog类型的对象,所以调用的是Dog对象的方法,而不是Animal对象的方法.


// 僵尸类 - 父类
@interface Zombie : NSObject
- (void) walk;
+ (void) haha;
@end
@implementation Zombie
- (void) walk {
        NSLog(@"Walk two steps.");    // 走两步
}
+ (void) haha {
        NSLog(@"HAHAHA!");
}
@end
 
// 跳跃僵尸类 - 子类
@interface JumpZombie : Zombie
- (void) walk;     // 重写走路动作为走之前跳两下.
@end
@implementation JumpZombie
- (void) walk {  
        NSLog(@"Jump twice.");       // 先跳两下
        [super walk];                          // 再调用父类的方法走两步
        // [super haha];  会出错. 父类没有 - haha方法,有的是+haha, 是两个不同的方法
}
@end



#  多态的好处 #

好处:   如果函数/方法的参数中使用父类类型,这样便可以用一个父类指针变量指向多个子类对象。可以传入父类对象,也可以传入子类对象。即用父类接受参数,节省代码。


比如, 我们有一个Cat,eat方法.还有一个Dog,也有eat方法.

@interface Cat : Animal
- (void) eat;
@end
 
@implementation Cat
- (void) eat {
        NSLog(@"Cat is eating");
}
@end
  
我们想写函数来喂动物, 喂Dog和Cat由于参数类型不同,需要对每种类型都写一个函数:
void feed(Dog *d) {
        [d eat];
}
void feed2(Cat *c ) {    // 不允许同名函数
        [c eat];
}
int main() {
        Dog *d = [Dog new];
        feed (d);      // 喂狗
        Cat *c = [Cat new];
        feed2 (c);    // 喂猫
        return 0;
}
这两个函数体是很相似的, 而且如果有更多的动物,还要写很多相似的函数,很麻烦,还要使用不同的名字.
 
可以使用多态来简化 - 写一个Animal类,作为Dog和Cat的父类,这样在函数中就可以使用Animal *指针,来指代Dog或Cat类型的参数:
void feed(Animal *a) {     // a既可以是Dog,也可以是Cat,也可以是其它Animal
        [a eat];         // 调用对象的eat方法.
}
int main() {
        Dog *d = [Dog new];
        feed (d);        // 调用的是Dog的eat方法
        Cat *c = [Cat new];
        feed (c);        // 调用的是Cat的eat方法
        Animal *a = [Animal new];
        feed (a);
}


这样只需要写一个函数, 很方便,而且调用的还都是每个对象自身的方法.



#多态的局限性#


动态绑定:调用方法时会监测对象的真实类型的方法。

 Animal中有   - (void)  eat;

      Dog中有       -  (void) eat;

    -  (void) run; 

即当两者有相同的方法时

Animal  *a = [Dog  new];

[a     eat];这样是可以的,调用Dog中的  eat方法。


不建议用父类指针调用子类的特有方法

 [a   run];

如果用父类指针调用子类在父类中没有的方法,虽然调用的是子类对象的方法,但是编译器会报警告,因为它只能看到用父类的指针调用一个父类没有的方法.


可以正确运行,但是编译器会警告.不建议这么写 (不建议写编译器会出警告的代码),代码不规范.

如果必须要这么写,规范方法是进行强制类型转换.

 Dog *d = (Dog *)a;

        [d       run];


#总结#

前提:有继承才有多态

多态:用父类指针指向子类对象

好处:可以用父类指针指代各种子类对象直接调用方法

局限:不建议用父类指针调用子类的特有方法,除非进行强制转换


NSString类的一些知识

#import <Foundation/Foundation.h>


int main()
{
    NSString *p = @"itcast"; // NSString字符串类,定义一个新的字符串
    
    NSLog(@"%@",p);
    
    int a = 10;
    int b = 20;
    NSString *_name = @"jack";
    
    NSString *newstr = [NSString stringWithFormat:@"there are %d students in the %d room,his name is%@",a,b,_name]; // 定义一个对象,newstr,然后把a,b,name都加上去,动态实现
    
    int s = [newstr length]; // 计算字符串的长度的方法,这是一个对象方法
    
    NSLog(@"%@,%d",newstr,s);
    
    return 0;
}



深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值