黑马程序员——入学Blog02----面向对象(下)

-----------android培训java培训iOS培训.Net培训期待与您交流!------------ 

         情境2:使用Objective-C的面向对象特性

//  main.m

#import <Foundation/Foundation.h>
#import "Graphic.h"
#import "WTriangle.h"
#import "WCircle.h"
#import "WSquare.h"
#import "WTools.h"
#define LENGHT 3
int main(int argc, const char * argv[])
{

    @autoreleasepool {
        double a,b,c;       // a,b,c为三边长
        double radius;      // radius为圆半径
        double width;       // width为边长
        double circum,area; // circum为图形周长,area为图形面积
        NSString *category;
        Graphic *graphic[LENGHT];                        // 声明一个图形类数组
        graphic[0] = [[WTriangle alloc] initWithGname:@"triangle" andCategory:WCategoryRuled]; // 数组的首元素是WTriangle对象
        graphic[1] = [[WCircle alloc] initWithGname:@"circle" andCategory:WCategoryRuled];     // 数组的第二个元素是WCircle对象
        graphic[2] = [[WSquare alloc] initWithGname:@"square" andCategory:WCategoryRuled];     // 数组的第三个元素是WSquare对象
        
        NSLog(@"Please input three length of triange:");
        scanf("%lf,%lf,%lf",&a,&b,&c);
        // a,b,c三条边是否能构成一个三角形
        if ([(WTriangle *)graphic[0] isValidA: a B:b andC:c])
        {
            [(WTriangle *)graphic[0] setA:a B:b andC:c];
        } // < 1 > 处测试封装
        NSLog(@"Please input the radius of circle:");
        scanf("%lf",&radius);
        [(WCircle *)graphic[1] setRadius:radius];
        
        NSLog(@"Please input the length of square:");
        scanf("%lf",&width);
        [(WSquare *)graphic[2] setWidth:width];
        // < 3 >
        for (int i = 0 ; i < LENGHT; i ++) {
            circum = [graphic[i] circum];
            area = [graphic[i] area];
            category =  [WTools tranformPrint:[graphic[i] category]];
            NSLog(@"\nThe perimeter of %@:%.2lf,area:%.2lf and %@",graphic[i].gname,circum,area,category);
        }
    }
    return 0;
}

//  TypeBean.h

#ifndef Blog01e_TypeBean_h
#define Blog01e_TypeBean_h

// 图形是否规则
typedef enum WCategory {
    WCategoryRuled,   // 规则图形
    WCategoryUnruled  // 不规则图形
} WCategory;

#endif



//  Graphic.h
// 继承自NSObject类,在这里作为其它类的父类
#import <Foundation/Foundation.h>
#import "TypeBean.h"
@interface Graphic : NSObject
{
    NSString *_gname;
    WCategory  _category;
}

// 类成员变量的getter && setter 方法 < 2 >
- (NSString *) gname;
- (void) setGname:(NSString *)gname;

- (WCategory) category;
- (void) setCategory:(WCategory)category;

// 利用图形名与图形规则进行初始化
- (Graphic *) initWithGname:(NSString *)gname andCategory:(WCategory)category;
// 获得图形周长的方法
- (double) circum;
// 获得图形面积的方法
- (double) area;
@end

//  图形类的实现
//  Graphic.m
#import "Graphic.h"

@implementation Graphic
// 类成员变量的getter && setter 方法
- (NSString *) gname
{
    return _gname;
}
- (void)setGname:(NSString *)gname
{
    self->_gname = gname;
}

- (WCategory) category
{
    return _category;
}
- (void) setCategory:(WCategory)category
{
    self->_category = category;
}


// 利用图形名与图形规则进行初始化
- (Graphic *) initWithGname:(NSString *)gname andCategory:(WCategory)category
{
    if (self = [super init])
    {
        self.gname = gname;
        self.category = category;
    }
    return self;
}

// 获得图形周长的方法
- (double) circum
{
    NSLog(@"子类负责实现这个方法");
    return 0.0;
}
// 获得图形面积的方法
- (double) area
{
    NSLog(@"子类负责实现这个方法");
    return 0.0;
}

@end

//  三角形类的声明
//  WTriangle.h

#import "Graphic.h"

@interface WTriangle : Graphic
{
    // 三角形的三边长
    double _a;
    double _b;
    double _c;
}

// 成员变量的getter方法
- (double) a;

- (double) b;

- (double) c;

// 同时为_a,_b,_c赋值
- (void) setA:(double)a B:(double)b andC:(double)c;
// 判断三边是否能构成三角形
- (BOOL) isValidA:(double)a B:(double)b andC:(double)c;
@end


// 三角形类的实现  <span style="white-space:pre">														</span>  // WTriangle.m

#import "WTriangle.h"
#import <math.h>
@implementation WTriangle
// 成员变量_a,_b,_c的get方法
- (double) a
{
    return _a;
}

- (double) b
{
    return _b;
}

- (double) c
{
    return _c;
}

// 同时为_a,_b,_c赋值
- (void) setA:(double)a B:(double)b andC:(double)c
{
    self->_a = a;
    self->_b = b;
    self->_c = c;<span style="white-space:pre">														</span>      // < 2 ><span style="white-space:pre">	</span>
}

// 重写父类的求周长方法
- (double)circum
{
    return self.a + self.b + self.c;
}

// 重写父类的求面积方法
- (double)area
{
    // p为三角形的半周长
    double p = (self.a + self.b + self.c) / 2.0;
    
    // 海伦公式求三角形的面积
    double st = sqrt(p * (p - self.a) * (p - self.b) * (p - self.c));
    return st;
}

// 判断三边是否能构成三角形
- (BOOL) isValidA:(double)a B:(double)b andC:(double)c;
{
    // 如果有一边为负数则返回NO
    if ( a < 0 || b < 0 || c < 0)
    {
        return NO;
    }
    // 任意两边之和大于第三边
    if (a + b > c && a + c > b && b + c > a)
    {
        return YES;
    }
    else
    {
        return NO;
    }

}
@end

//  圆形类的声明
//  WCircle.h

#import "Graphic.h"

@interface WCircle : Graphic
{
    double _radius;
}
// 半径的getter && setter方法
- (double) radius;
- (void)setRadius:(double)radius;
@end

// 圆形类的实现  <span style="white-space:pre">															</span>  // WCircle.m

#import "WCircle.h"
#import <math.h>
#define PI 3.14
@implementation WCircle
// 半径的getter && setter方法
- (double) radius
{
    return _radius;
}
- (void)setRadius:(double)radius
{
    self->_radius = radius;
}

// 重写父类的求周长方法
- (double)circum
{
    return 2 * PI * self.radius;
}

// 重写父类的求面积方法
- (double) area
{
    return PI * pow(self.radius, 2);
}
@end

//  正方形类的声明
//  WSquare.h

#import "Graphic.h"

@interface WSquare : Graphic
{
    double _width;  // 正方形的边长
}

// 正方形边长的getter && setter方法
- (double) width;
- (void) setWidth:(double)width;
@end

//  正方形类的实现
//  WSquare.m

#import "WSquare.h"

@implementation WSquare


// 正方形边长的getter && setter方法
- (double) width
{
    return _width;
}
- (void) setWidth:(double)width
{
    self->_width = width;
}

// 重写父类的求周长的方法
- (double)circum
{
    return 4 * self.width;
}

// 重写父类的求面积的方法
- (double) area
{
    return pow(self.width, 2);
}
@end

//  工具类的声明
//  WTools.h


#import <Foundation/Foundation.h>
#import "TypeBean.h"
@interface WTools : NSObject
// 将枚举值转换为对应的字符串
+ (NSString *)tranformPrint:(WCategory)category;
@end

//  工具类的实现
//  WTools.m

#import "WTools.h"

@implementation WTools

// 将枚举值转换为对应的字符串
+ (NSString *)tranformPrint:(WCategory)category
{
    if (category == WCategoryRuled)
    {
        return @"it's rule";
    }
    else
    {
        return @"it's not rule";
    }

}
@end

运行结果:



  1. 封装

          在 main.m的 < 1 > 处 添加如下代码

WTriangle *triangle = [[WTriangle alloc] init];
triangle->_a = -1;

        Xcode报错  

         证明对象的成员变量不能直接被修改,且默认的访问修饰符是@protected,保证了对象的成员变量不会获得不合理的值,还有3种访问修饰符@protected,@package,@private,但@package修饰符不常用,所以剩下3个修饰符的开放程度@public > @protected > @private

      2. 继承

         在这道题中,类WTriangle,WCircle,WSquare继承了类Graphic,而类Graphic继承自类NSObject,因为OC是单继承的,所以子类与父类的关系是多对一,因为类WTriangle,WCircle,

WSquare继承自Graphic类,且成员变量的访问修饰符是@protected,所以子类可以访问父类的成员变量,即在WTriangle.m的 < 2 >添加如下代码

self->_gname = @"Dimend";
       Xcode不报错,证明WTriangle类有_gname这个成员变量,通过继承子类得到了父类中得成员变量,实现了代码的复用。反过来从父类到子类的过程看,比如WTriangle需要的是_a,_b,_c三边,而WCircle需要的是_radius,子类可以根据需求扩展父类,而且不需要更改父类的内容。实现了对代码扩展的开放,修改的关闭。


      3.  多态

         在 main.m的 < 3 > 处 实现了多态的特性,多态的表现是父类的指针指向子类对象,而能够实现多态是因为动态绑定。关于动态绑定的解释百度百科上是这么定义的:指在执行期间(非编译期)判断所引用对象的实际类型,根据其实际类型调用其相应的方法。

         在这里的代码体现在 graphic[0]应该是一个指向Graphic类的指针,但是实际拿到的是一个WTriangle类。调用graphic[0]的area方法,实际被调用的是对象WTriangle的area方法,而不是声明graphic[0]指针的Graphic对象的area方法。

graphic[0] = [[WTriangle alloc] initWithGname:@"triangle" andCategory:WCategoryRuled]; 						  [graphic[i] area];
          使用多态可以屏蔽子类对象之间的差异,关注子类对象之间的共同点,让代码简洁。但是多态也有它的局限性,比如main.m中的,graphic[1]在编译期被认为是一个Graphic类对象,所以,如果不使用强制转换 

[graphic[1] setRadius:radius];
        Xcode 将报 的错误,因为它认为这是一个Graphic类对象,自然找不到setRadius这个方法。


       在上面的代码中,出现了一些有待说明的地方。

      1. self 与 super 关键字,方法的修饰符 + / -

      2. 对象的init方法

      3. 父类Graphic的circum与area,不应该实现,因为任何一个具体图形都不应该调用这两个方法

// 获得图形周长的方法
- (double) circum
{
    NSLog(@"子类负责实现这个方法");
    return 0.0;
}
// 获得图形面积的方法
- (double) area
{
    NSLog(@"子类负责实现这个方法");
    return 0.0;
}

      4. 不同类的setter 与 getter 方法大同小异。

        


      




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值