• 面向对象的个人理解(封装/继承/多态实践)


    目录

    前言

    为什么要封装?

     为什么要继承?

    什么是多态?


    前言

    计算机科学是一门实践性很强的科目,所有理论都不是凭空而来的,某种理论的出现都是为了解决过往的不足。面向对象是其中之一,但我们不能单从字面去理解面向对象这个新名词,而是通过实践,从面向过程自然过渡到面向对象中来。

    本文假设有一个宠物模拟系统,每个宠物都是一个相对独立的子系统,因为它们有着各自的特性,为了模拟现实中的宠物,在逻辑上每个宠物也应该当成独立的个体来编写代码,这样有助于人类的理解。

    注:

    文中的代码主要是一些说明问题的伪代码,如果想运行起来,需要读者自行发挥想象力,补充完善。

    另外,C语言在命令行下边会有中文乱码问题,尽量使用Visual studio来写程序,可以省去很多麻烦。

    为什么要封装?

    封装是为了将某些相关联的数据和操作进行隔离,放在一个独立的容器里。在编程语言中,这个窗口叫啊类,将类加载到内存,初始后变成一个独立可访问的数据块,这个数据块就成了一个对象。

    在本文的示例中,类相当于对各种宠物的文字描述,对象(或实例)是一个个实际的宠物个体。

    我们先用不面对对象的C来设计一个宠物模拟程序,先不看实现,只看定义。假设家里刚开始只有一只哈士奇,为了模拟狗狗的日常,我们在头文件里如此定义:

    1. /*狗狗*/
    2. #pragma once
    3. #include
    4. typedef struct
    5. {
    6. wchar_t* name;//名字
    7. int age;//年龄
    8. char gender;//性别
    9. int color;//颜色
    10. int hp;//健康值
    11. int fp;//怒值,达到一定程度会咬人
    12. int exps;//友好值,低到一定程序会离家出走
    13. }Pet;
    14. /*
    15. * 呼唤宠物
    16. */
    17. void call();
    18. /*
    19. * 抚摸宠物
    20. */
    21. void touch();
    22. /*打狗*/
    23. void beat();
    24. /*会叫*/
    25. void bark();
    26. /*会咬人*/
    27. void bite();
    28. /*离家出走,消失不见*/
    29. void hide();
    30. /*溜狗*/
    31. void walk();

     后来又抱了只猫,猫跟狗狗一样都是用来撸的,只是猫不用溜,但要准备猫沙,还会抓老鼠,要给它铲屎,本来猫的头文件应该定义成这样:

    1. /*猫咪*/
    2. #pragma once
    3. #include
    4. typedef struct
    5. {
    6. wchar_t* name;//名字
    7. int age;//年龄
    8. char gender;//性别
    9. int color;//颜色
    10. int hp;//健康值
    11. int fp;//怒值,达到一定程度会咬人
    12. int exps;//友好值,低到一定程序会离家出走
    13. }Pet;
    14. /*
    15. * 呼唤宠物
    16. */
    17. void call();
    18. /*
    19. * 抚摸宠物
    20. */
    21. void touch();
    22. /*打猫*/
    23. void beat();
    24. /*会叫*/
    25. void bark();
    26. /*会咬人*/
    27. void bite();
    28. /*离家出走,消失不见*/
    29. void hide();
    30. /*铲屎*/
    31. void clean();
    32. /*抓老鼠*/
    33. void catchmouse();

     但这样一来,编译器会重复定义的错误,所以改方法名,以示区别,可以每个方法前添加前缀来实现,变成这样:

    1. /*猫咪*/
    2. #pragma once
    3. #include
    4. typedef struct
    5. {
    6. wchar_t* name;//名字
    7. int age;//年龄
    8. char gender;//性别
    9. int color;//颜色
    10. int hp;//健康值
    11. int fp;//怒值,达到一定程度会咬人
    12. int exps;//友好值,低到一定程序会离家出走
    13. }Pet;
    14. /*
    15. * 呼唤宠物
    16. */
    17. void catcall();
    18. /*
    19. * 抚摸宠物
    20. */
    21. void cattouch();
    22. /*打猫*/
    23. void catbeat();
    24. /*会叫*/
    25. void catbark();
    26. /*会咬人*/
    27. void catbite();
    28. /*离家出走,消失不见*/
    29. void cathide();
    30. /*铲屎*/
    31. void catclean();
    32. /*抓老鼠*/
    33. void catcatchmouse();

     看上去好像解决问题了,但指不定哪天又养只鹦鹉,养了条黄金莽什么的,那就不断往上加吧,如果没有重样的宠物还好,但遇到重样的又麻烦了,比如狗狗生了小狗,鹦鹉生了蛋等等,虽然技术上是可以解决的,比如每个狗狗函数加上参数,以标明是哪只狗,但这样会变得非常的混乱,修改量也不是一般的大。

    我们再用Java实现一遍看看,先写个Dog类:

    1. public class Dog {
    2. String name;//名字
    3. int age;//年龄
    4. char gender;//性别
    5. int color;//颜色
    6. int hp;//健康值
    7. int fp;//怒值,达到一定程度会咬人
    8. int exps;//友好值,低到一定程序会离家出走
    9. public void call()
    10. {
    11. exps += 100;
    12. System.out.println(String.format("%s,过来!", name));
    13. System.out.println("汪汪汪");
    14. System.out.println(String.format("好感度值增加100!当前好感度:%d", exps));
    15. }
    16. public void touch()
    17. {
    18. exps += 200;
    19. System.out.println(String.format("摸一摸%s!\n", name));
    20. System.out.println("汪汪!");
    21. System.out.println(String.format("好感度值增加200!当前好感度:%d\n", exps));
    22. }
    23. public void beat()
    24. {
    25. }
    26. public void bark()
    27. {
    28. }
    29. public void bite()
    30. {
    31. }
    32. public void hide()
    33. {
    34. }
    35. public void walk()
    36. {
    37. }
    38. }

    然后复制一份,改个类名,修改少部分内容基本就OK了: 

    1. public class Cat {
    2. String name;//名字
    3. int age;//年龄
    4. char gender;//性别
    5. int color;//颜色
    6. int hp;//健康值
    7. int fp;//怒值,达到一定程度会咬人
    8. int exps;//友好值,低到一定程序会离家出走
    9. public void call()
    10. {
    11. exps += 100;
    12. System.out.println(String.format("%s,过来!", name));
    13. System.out.println("喵喵喵");
    14. System.out.println(String.format("好感度值增加100!当前好感度:%d", exps));
    15. }
    16. public void touch()
    17. {
    18. exps += 200;
    19. System.out.println(String.format("摸一摸%s!\n", name));
    20. System.out.println("喵喵!");
    21. System.out.println(String.format("好感度值增加200!当前好感度:%d\n", exps));
    22. }
    23. public void beat()
    24. {
    25. }
    26. public void bark()
    27. {
    28. }
    29. public void bite()
    30. {
    31. }
    32. public void hide()
    33. {
    34. }
    35. void catclean()
    36. {
    37. }
    38. void catcatchmouse()
    39. {
    40. }
    41. }

     为什么要继承?

    虽然CTRL+V、CTRL+C很爽,但如果有一天,想换个姿势撸宠物,比如要小动物都要亲亲或者抱抱,如果宠物少的情况下,每个宠物类里加两个方法倒也不是难事,但万一家里小可爱们太多了,有十几上百个,那改起来是要命的,那能不像动物学那样,可以将宠物按某种分类,层层向下扩展。答案是可以的。

    不管是猫是狗还是鹦鹉,它们都有个共同称呼,叫宠物,OK,我们可以定义一个宠物的类Pet:

    1. public class Pet {
    2. protected String name;// 宠物都有名字
    3. protected int age;// 宠物都有寿命
    4. protected char gender;// 宠物都分雌雄
    5. protected int color;// 宠物都有颜色
    6. protected int hp;// 宠物都要追踪健康情况
    7. protected int fp;// 宠物都在某些情况都会生气,达到一定程度会咬人
    8. protected int exps;// 宠物都跟主人都有亲密程度,低到一定程序会离家出走
    9. /**
    10. * 宠物都能被呼唤
    11. */
    12. public void call() {
    13. exps += 100;
    14. System.out.println(String.format("%s,过来!", name));
    15. System.out.println(String.format("好感度值增加100!当前好感度:%d", exps));
    16. }
    17. /**
    18. * 宠物都可以摸
    19. */
    20. public void touch() {
    21. exps += 200;
    22. System.out.println(String.format("摸一摸%s!\n", name));
    23. System.out.println(String.format("好感度值增加200!当前好感度:%d\n", exps));
    24. }
    25. }

    然后再修改具体宠物的类比如狗:

    1. /**
    2. * 狗狗
    3. *
    4. */
    5. public class Dog extends Pet {
    6. /**
    7. * 狗会叫
    8. */
    9. public void bark()
    10. {
    11. System.out.println("汪汪!");
    12. }
    13. }

    再改下猫:

    1. /**
    2. * 猫猫
    3. *
    4. */
    5. public class Cat extends Pet {
    6. /**
    7. * 猫会妙妙
    8. */
    9. public void Miaow() {
    10. System.out.println("喵喵");
    11. }
    12. }

    接着,我们给宠物们都增加亲亲抱抱的功能,只要修改Pet这个类就行了:

    1. /**
    2. * 小可爱们
    3. *
    4. */
    5. public class Pet {
    6. protected String name;// 宠物都有名字
    7. protected int age;// 宠物都有寿命
    8. protected char gender;// 宠物都分雌雄
    9. protected int color;// 宠物都有颜色
    10. protected int hp;// 宠物都要追踪健康情况
    11. protected int fp;// 宠物都在某些情况都会生气,达到一定程度会咬人
    12. protected int exps;// 宠物都跟主人都有亲密程度,低到一定程序会离家出走
    13. /**
    14. * 宠物都能被呼唤
    15. */
    16. public void call() {
    17. exps += 100;
    18. System.out.println(String.format("%s,过来!", name));
    19. System.out.println(String.format("好感度值增加100!当前好感度:%d", exps));
    20. }
    21. /**
    22. * 宠物都可以摸
    23. */
    24. public void touch() {
    25. exps += 200;
    26. System.out.println(String.format("摸一摸%s!\n", name));
    27. System.out.println(String.format("好感度值增加200!当前好感度:%d\n", exps));
    28. }
    29. /**
    30. * 亲亲
    31. */
    32. public void kiss() {
    33. exps += 200;
    34. System.out.println("啾啾");
    35. }
    36. /**
    37. * 亲亲
    38. */
    39. public void embrace() {
    40. exps += 200;
    41. System.out.println("抱抱");
    42. }
    43. }

    什么是多态?

    不同的宠物,虽然在主人眼中是一样的,但撸完会有不同的反应,这些行为是动物自己做出来的,只有具体到每个宠物本身,主人才能体验到各个宠物的反应。但抽象点说,宠物是用来撸的,主人可能并不在意宠物的具体反应,而是享受这个互动的过程。所以多态就是抽象层面的一致,而具体层面的不一致。

    比如狗狗:

    1. /**
    2. * 狗狗
    3. *
    4. */
    5. public class Dog extends Pet {
    6. @Override
    7. public void touch() {
    8. super.touch();
    9. //摸玩狗狗,它会冲着你叫
    10. bark();
    11. }
    12. /**
    13. * 狗会叫
    14. */
    15. public void bark()
    16. {
    17. System.out.println("汪汪!");
    18. }
    19. }

    比如猫:

    1. /**
    2. * 猫猫
    3. *
    4. */
    5. public class Cat extends Pet {
    6. @Override
    7. public void touch() {
    8. super.touch();
    9. //猫会打呼噜
    10. System.out.println("呼噜噜~");
    11. }
    12. /**
    13. * 猫会妙妙
    14. */
    15. public void Miaow() {
    16. System.out.println("喵喵");
    17. }
    18. }

    比如鹦鹉:

    1. /**
    2. * 鹦鹉
    3. *
    4. */
    5. public class Parrot extends Pet {
    6. @Override
    7. public void touch() {
    8. exps -= 50;
    9. // 鹦鹉直接开口骂娘
    10. System.out.println("烦死了~");
    11. }
    12. }

    以上示例中,每个宠物都有touch()的功能,也就是被撸这一点是一致的。主人对待宠物时,在这点上一致的。但同时宠物可能在被撸后,表现出所有宠物共同的反应,也可能是自己独特的反应。比如猫狗都调用了super.touch(),说明猫狗被撸时会表现出一些共同的特性。而鹦鹉则完全特立独行,还降低了好感度。

  • 相关阅读:
    PyTorch常用参数初始化方法详解
    一种基于体素的射线检测
    【mysql为什么采用b+树作为索引】
    ctfshow 反序列化篇(下)
    K8s 集群高可用master节点ETCD挂掉如何恢复?
    CSS 选择器
    Redux Toolkit中action派发但state值不更新的原因
    DW大学生网页作业制作设计 ——旅游门户网站(21页)HTML+CSS+JavaScript
    阿里云天池大赛赛题(机器学习)——工业蒸汽量预测(完整代码)
    vi 连线板.
  • 原文地址:https://blog.csdn.net/icoolno1/article/details/108640125