Objective-C是一门以C为基础的面向对象编程语言,具有封装,继承,多态的特性。为什么要使用面向对象,或者说面向过程有哪里不够好?下面举例说明我的看法。
问题:求任意三角形,圆形以及正方形的周长与面积
情境1:不使用面向对象的特性
//
// 题目:求出任意三角形,圆,正方形的周长与面积
//
#import <Foundation/Foundation.h>
#import <stdio.h>
#import <math.h>
#import "TypeBean.h"
#import "WTools.h"
#import "WTriangle.h"
#import "WCircle.h"
#import "WSquare.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
double a,b,c,st=0,ct=0; // a,b,c为三边长,st为三角形面积,ct为三角形的周长
double radius,sc=0,cc=0; // radius为圆半径,sc为圆面积,cc为圆周长
double width,ss=0,cs=0; // width为边长,ss为正方形面积,cs为正方形周长
WTriangle triangle;
WCircle circle;
WSquare square;
char *category = (char *)(malloc(sizeof(char *)));
NSLog(@"\nPlease input three length of triangle:");
scanf("%lf,%lf,%lf",&a,&b,&c);
// 如果a,b,c 能构成三角形
if (isVaild(a, b, c))
{
// 设置三角形的三边
triangle = setTriangle(a, b, c);
// 三角形的面积
st = areaOfTriangle(triangle);
// 三角形的周长
ct = circumOfTriangle(triangle);
// 将枚举值转换为对应的字符串
category = tranformPrint(triangle._category);
// < 1 >
// triangle._a = -1;
NSLog(@"\nThe perimeter of %s:%.2lf,area:%.2lf,and %s",triangle._gname,ct,st,category);
}
NSLog(@"Please input the radius of circle:");
scanf("%lf",&radius);
// 设置圆
circle = setCircle(radius);
// 求出圆的面积
sc = areaOfCircle(circle);
// 求出圆的周长
cc = circumOfCircle(circle);
// 将枚举值转换为对应的字符串
category = tranformPrint(circle._category);
NSLog(@"\nThe perimeter of %s:%.2lf,area:%.2lf,and %s",circle._gname,cc,sc,category);
NSLog(@"Please input the length of square:");
scanf("%lf",&width);
// 设置正方形
square = setSquare(width);
// 求出正方形的周长
cs = circumOfSquare(square);
ss = areaOfSquare(square);
// 将枚举值转换为对应的字符串
category = tranformPrint(square._category);
NSLog(@"\nThe perimeter of %s:%.2lf,area:%.2lf,and %s",square._gname,cs,ss,category);
}
return 0;
}
// TypeBean.h
// 数据结构的定义
#ifndef Blog01_TypeBean_h
#define Blog01_TypeBean_h
// 图形是否规则
typedef enum WCategory {
WCategoryRuled, // 规则图形
WCategoryUnruled // 不规则图形
} WCategory;
// 定义一个三角形结构体
typedef struct WTriangle {
// a,b,c为三边长
double _a;
double _b;
double _c;
WCategory _category; // < 2 >
char _gname[20]; // 图形的名称
} WTriangle;
// 定义一个圆形结构体
typedef struct WCircle {
// radius为圆的半径
double _radius;
WCategory _category; // < 3 >
char _gname[20];
} WCircle;
// 定义一个正方形结构体
typedef struct WSquare{
// width为正方形的边长
double _width;
WCategory _category;
char _gname[20];
} WSquare;
#endif
// WTriangle.h
#ifndef Blog01_WTriangle_h
#define Blog01_WTriangle_h
BOOL isVaild(double a,double b, double c); // 判断a,b,c是否可以组成三角形
WTriangle setTriangle(double a,double b,double c); // 设置a,b,c为三角形的三边
double areaOfTriangle(WTriangle triangle); // 求出指定三角形的面积
double circumOfTriangle(WTriangle triangle); // 求出指定三角形的周长
#endif
// WTriangle.m
// 三角形的相关函数
#import "TypeBean.h"
#import "WTriangle.h"
// 判断a,b,c是否可以组成三角形
BOOL isVaild(double a,double b,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;
}
}
// 设置a,b,c为三角形的三边
WTriangle setTriangle(double a,double b,double c)
{
WTriangle triangle;
triangle._a = a;
triangle._b = b;
triangle._c = c;
triangle._category = WCategoryRuled;
strcpy(triangle._gname, "triangle");
return triangle;
}
// 求出指定三角形的面积
double areaOfTriangle(WTriangle triangle)
{
// p为三角形的半周长
double p = (triangle._a + triangle._b + triangle._c) / 2.0;
// 海伦公式求三角形的面积
double st = sqrt(p * (p - triangle._a) * (p - triangle._b) * (p - triangle._c));
return st;
}
// 求出指定三角形的周长
double circumOfTriangle(WTriangle triangle)
{
return triangle._a + triangle._b + triangle._c;
}
// WCircle.h
#ifndef Blog01_WCircle_h
#define Blog01_WCircle_h
WCircle setCircle(double radius); // 设置radius为圆的半径
double circumOfCircle(WCircle circle); // 求出指定圆的周长
double areaOfCircle(WCircle circle); // 求出指定圆的面积
#endif
// WCircle.m
// 圆的相关函数
#import "TypeBean.h"
#define PI 3.14 // 定义圆周率常量
// 设置圆
WCircle setCircle(double radius)
{
WCircle circle;
circle._radius = radius;
circle._category = WCategoryRuled;
strcpy(circle._gname,"circle");
return circle;
}
// 求出圆周长
double circumOfCircle(WCircle circle)
{
return 2 * PI * circle._radius;
}
// 求出指定圆的面积
double areaOfCircle(WCircle circle)
{
// 圆面积 = 圆周率 * 半径的平方
return PI * pow(circle._radius, 2);
}
// WSquare.h
#ifndef Blog01_WSquare_h
#define Blog01_WSquare_h
WSquare setSquare(double width); // 设置正方形的边长
double circumOfSquare(WSquare square); // 求出正方形的周长
double areaOfSquare(WSquare square); // 求出正方形的面积
#endif
// WSquare.m
// 正方形的相关函数
#import "TypeBean.h"
// 设置正方形的边长
WSquare setSquare(double width)
{
WSquare square;
square._width = width;
square._category = WCategoryRuled;
strcpy(square._gname,"square");
return square;
}
// 求出正方形的周长
double circumOfSquare(WSquare square)
{
return square._width * 4;
}
// 求出正方形的面积
double areaOfSquare(WSquare square)
{
return pow(square._width, 2);
}
// WTools.h
#ifndef Blog01_WTools_h
#define Blog01_WTools_h
char * tranformPrint(WCategory category); // 将枚举值转换为字符串
#endif
// WTools.m
// 工具函数
#import "TypeBean.h"
// 将枚举值转换为字符串
char * tranformPrint(WCategory category)
{
if (category == WCategoryRuled)
{
return "it's rule";
}
else
{
return "it's not rule";
}
}
// triangle._a = -1;
没有进行数据的过滤,可以直接通过 结构体.成员变量 = 变量名; 直接对结构体成员变量赋值,缺少封装的特性,不安全
比较 TypeBean.h 的< 2 > 与 < 3 >
WCategory _category;
char _gname[20];
多个结构体拥有相同的成员变量,代码重复,以后添加菱形,椭圆形等,还是要添加相同的成员变量,没有继承,代码冗余
观察 main.m,三角形,圆形,正方形都有求面积,周长的函数,但是因为具体的计算方法不同出现多个功能类似的函数,可以使用多态改进。
下一篇将通过使用面向对象的方式解决这个问题,进行对比
下一篇将通过使用面向对象的方式解决这个问题,进行对比
注:开发环境 OS X Mavericks 10.9.4 Xcode 4.6.3