学习面向对象的思维

And*_*eas 43 oop

我目前正在研究一种用C++编写的小型2D游戏引擎,但我现在正面临一个守护进程 - 我很擅长设计一个实际可行的"类系统".在我的脑海中有一个封锁,使我无法看到我应该在哪里使用课堂以及我不应该在哪里.我正在阅读一篇关于引擎设计的文章,它的目的是使用'State'类来管理不同游戏条目的状态(我使用的是int).它还表明游戏的所有对象(不是io /视频/声音等)都来自Renderable或NonRenderable类.这很聪明.我已经知道这是一种聪明的方式 - 我的意思是,Java中的每个对象都是基类Object吗?聪明,我知道!为什么我不那样做?我需要阅读什么才能真正融入这种心态?

另一个例子.我正在参加Ruby的夏季课程(非常简单),我们应该设计一个露营地点.简单!因此,露营地是一系列"地块",每个都有一个电量计,用于衡量客人消耗的电量.我的设计是三个类,一个用于露营 - 反​​过来使用Guest和Plot类的数组.我的老师建议我多上课.WTF(!)是我的第一个想法,在哪里,什么课程?在我看来,一切都是一个阶级 - 直到我意识到,也许规范应该是一个类?现在,仪表是Plot类中的整数.

我想学习如何为我的问题提出面向对象的解决方案 - 而不仅仅是如何让最明显的东西进入课堂!

提示/书籍/文章/博客?

我在CS学习了两年,并且多年来一直作为业余爱好进行编程!我只是被卡住了 - 这让我无法创建任何更大的软件!

Dan*_*nas 21

我个人的经验是使用Bertrand Meyer 学习面向对象软件构建,面向对象软件构建,第2版.

这本书对我来说非常宝贵,而且仍然是我从中学到的关于OO编程和软件构建的一本书.

以下是它的一些优点:

  • A部分:问题,一个非常好的软件质量定义.
  • B部分:面向对象的道路上,一种逻辑的,逐步搜索面向对象技术的方式,使读者认为调查正在进行中,也就是说,好像还没有已知的结果.你可能会从这部分获得你正在寻找的心态.
  • C部分:面向对象技术(本书的技术核心)中,您将使您的知识扎实并学习有关按合同设计,继承,通用等方面的非常有用的技巧.
  • D部分:OO方法:很好地应用该方法是一种更实用的设计方法,我也觉得非常有用.请参阅例如如何查找在线查找的类(22).

在这些部分之后,会出现更多高级主题,例如Concurrency(30)Databases(31).

由于这本书使用了埃菲尔语(由作者设计),这将使你有正确的心态并教你思考.将这些想法应用于其他或多或少的OO编程语言将很容易.

  • @dfa你能解释为什么它是最具侵略性的...只是好奇.顺便说一下,我还没有读过这本书......计划拿到一本书 (4认同)
  • +1:有史以来最具争议性的书之一,但我喜欢它 (2认同)

Dav*_*vis 13

面向对象

面向对象的编程就是要求对象做一些事情:一个看似难以正确应用的概念.

Goban

考虑一个2D游戏板,就像玩Go(称为goban)一样.

首先考虑完成任务所需的行为.这意味着列出对象的行为,而不是决定行为操纵的数据.例如,基本板可能具有以下行为:

  • 放一块石头.
  • 删除Go石头.
  • 去掉所有的石头.

对于Go的计算机版本,可以方便地关注特定区域:

  • 标记交叉点(例如,三角形,数字,字母,圆形,正方形).
  • 从标记的交叉点移除标记.
  • 删除所有标记.

请注意,goban不需要提供一种方法来为客户提供特定交叉点处石头的引用.相反,它可以回答有关其状态的问题.例如,goban可能会回答以下问题:

  • 在给定的十字路口有黑色的石头吗?
  • 在给定的十字路口是否有白色的石头?
  • 在给定的交叉点是否有标记?

它是不是有责任goban知道游戏的状态:属于一个实例游戏(有规则).在现实生活中,goban只是石头的舞台.

此时,我们可以在不知道底层实现如何工作的情况下为goban编写接口.

public interface Goban {
  public void place( Stone stone, Point point );

  public void removeStone( Point point );
  public void removeStones();

  public void place( Mark mark, Point point );

  public void removeMark( Point point );
  public void removeMarks();

  public boolean hasWhiteStone( Point point );
  public boolean hasBlackStone( Point point );
  public boolean hasMark( Point point );
}
Run Code Online (Sandbox Code Playgroud)

注意董事会如何与规则游戏完全分开.这使得goban可以重复用于其他游戏(涉及石头和十字路口).该goban可以从通用接口(如继承董事会接口),但这应该足以解释认为,在对象方面的一种方式.

封装

的的实现Goban接口不暴露其内部数据.此时,我可以请求您实现此接口,编写单元测试,并在完成后将编译的类发送给我.

我不需要知道您使用了哪些数据结构.我可以使用你的实现来玩(并描绘)一个Goban.这是许多项目出错的关键点.许多项目代码如下:

public class Person {
  private HairColour hairColour = new HairColour( Colour.BROWN );

  public Person() {
  }

  public HairColour getHairColour() {
    return hairColour;
  }

  public void setHairColour( HairColour hairColour ) {
    this.hairColour = hairColour;
  }
}
Run Code Online (Sandbox Code Playgroud)

这是无效的封装.考虑鲍勃不喜欢将头发染成粉红色的情况.我们可以做到以下几点:

public class HairTrickster {
  public static void main( String args[] ) {
    Person bob = new Person();
    HairColour hc = bob.getHairColour();
    hc.dye( Colour.PINK );
  }
}
Run Code Online (Sandbox Code Playgroud)

鲍勃现在的头发是粉红色的,没有什么能阻止它.有办法避免这种情况,但人们不这样做.相反,封装被破坏导致僵硬,不灵活,错误缠身且不可维护的系统.

实施封装的一种可能方法是返回克隆HairColour.修改后的Person类现在很难将头发颜色更改为Pink.

public class Person {
  private HairColour hairColour = new HairColour( Colour.BROWN );

  public Person() {
  }

  public HairColour getHairColour() {
    return hairColour.clone();
  }

  public void setHairColour( HairColour hairColour ) {
    if( !hairColour.equals( Colour.PINK ) {
      this.hairColour = hairColour;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

鲍勃可以安然入睡,因为他知道自己不会醒来做粉红染色工作.


j_r*_*ker 9

值得记住的是:OO本身并不是目的. OO的目的是在产品的整个生命周期中使开发,特别是代码的维护更容易.谨防"OO为OO着想"的心态.


chi*_*kak 6

首先是面向对象的分析与设计

我喜欢Head First Books,因为它们阅读起来很有趣.他们有练习和谜题来划伤你的头脑.我读过这本书并发现它非常好.

这本书包括:

  • 使用OO原则(封装和委托)
  • 开闭原理(OCP)
  • 单一责任原则(SRP)
  • 设计模式,UML,用例等

  • 当你推荐一本书时,不要只发布一个链接 - 解释为什么它是一本好书并解决问题. (2认同)