技术宅,fat-man

增加语言的了解程度可以避免写出愚蠢的代码

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

C语言实现OOP 版本2

写版本2的原因,还是发现在不同的具体图形模块里发现了重复的release代码,这是坏味道,所以还是决定消除这些重复代码,DRY


shape.h

复制代码
#ifndef SHAPE_H
#define SHAPE_H

typedef struct shape_t 
{
    void *shapeData;
    void (*area)(void *);
    void (*release)(void *);
}Shape;

void release(void *shape);

#endif
复制代码

shape.c

#include <stdlib.h>
#include "shape.h"

void release(void *shape)
{
    free(((Shape*)shape)->shapeData);
    free(shape);
}

circle.h

复制代码
#ifndef CIRCLE_H
#define CIRCLE_H

typedef struct
{
    double r;
}CircleData;

typedef struct 
{
    void *shapeData;
    void (*area)(void *);
    void (*release)(void *);
}Circle;

Circle *makeCircle(double r);

#endif
复制代码

circle.c

复制代码
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "shape.h"
#include "circle.h"

const double PI = 3.14159;

static void area(void *shape)
{
    Circle *_circle = (Circle *)shape;
    CircleData* data = (CircleData*)_circle->shapeData;
    printf("the circle area is %f \n", data->r * data->r * PI);
}

/*
static void release(void *shape)
{
    Circle *_circle = (Circle *)shape;
    CircleData* data = (CircleData*)_circle->shapeData;
    free(data);
    free(_circle);
}
*/

Circle *makeCircle(double r)
{
    CircleData* circleData = (CircleData*)malloc(sizeof(CircleData));
    Circle* circle = (Circle*)malloc(sizeof(Circle));
    assert(circleData != NULL);
    assert(circle != NULL);
    assert(r > 0);

    
    circleData->r = r;
    circle->shapeData = circleData;
    circle->area = &area;
    circle->release = &release;

    return circle;
}
复制代码

square.h

复制代码
#ifndef SQUARE_H
#define SQUARE_H

typedef struct
{
    double x;
    double y;
}SquareData;

typedef struct 
{
    void *shapeData;
    void (*area)(void *);
    void (*release)(void *);
}Square;

Square *makeSquare(double x, double y);

#endif
复制代码

square.c

复制代码
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "shape.h"
#include "square.h"

static void area(void *shape)
{
    Square *square = (Square *)shape;
    SquareData* data = (SquareData*)square->shapeData;
    printf("the square area is %f \n", data->x * data->y);
}

/*
static void release(void *shape)
{
    Square *square = (Square *)shape;
    SquareData* data = (SquareData*)square->shapeData;
    free(data);
    free(square);
}
*/

Square *makeSquare(double x, double y)
{
    SquareData* squareData = (SquareData*)malloc(sizeof(SquareData));
    Square* square = (Square*)malloc(sizeof(Square));
    assert(squareData != NULL);
    assert(square != NULL);
    assert(x > 0 && y > 0);

    squareData->x = x;
    squareData->y = y;
    square->shapeData = squareData;
    square->area = &area;
    square->release = &release;

    return square;
}
复制代码

main.c 发现没有,尽管内部进行了调整,这些的代码丝毫没变!重构就应该这样,内部的调整不太涉及到client代码,除非真的决定修改接口,修改接口内部应该优先于调整接口

复制代码
#include <stdio.h>
#include "shape.h"
#include "circle.h"
#include "square.h"

void printShapeArea(Shape **shape,int length)
{
    int i=0;
    for(i=0;i<length;i++)
    {
        shape[i]->area(shape[i]);
        shape[i]->release(shape[i]);
    }
}

int main()
{
    Shape *p[3] = {(Shape*)makeCircle(3.2),(Shape*)makeCircle(3.2),(Shape*)makeSquare(3.1,4)};
    printShapeArea(p,3);
    return 0;
}
复制代码

 

 

 

 

 

 

posted on   codestyle  阅读(410)  评论(0编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
历史上的今天:
2012-07-27 python:可变参数与apply
2012-07-27 重构实例1:抽取冗余代码 - 未通过测试而进行的第二次修正
点击右上角即可分享
微信分享提示