首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

面向对象的编程-Application 61

Previously on OOP:

关于最后一项大作业,本黄鸭还有几个comments需要补充:

(1)在requirement 4, Statistics中,要求选出朋友最多的用户,题目中有一句话是“Do not consider the case of ties.”在Oxford dictionary中,tie作为名词有一个意向:

所以,我们不需要考虑并列第一名的情况。

(2)每个.java文件的开头都有一些Java libraries要被import进来,有的可以通过编译器自动生成,而有的必须手动输入,比如:

我们可以在每个.java文件(尤其是主的类)的开头都粘贴上这两行字,以防止需要用到Stream collectors/Comparator。

(3)Map类中还有一个已经定义好的函数叫做keyset(),和entrySet()函数很像:

entrySet()除了能把Map的一个key field和对应的value field打包成一个entry之外,还能把并列名次的几个Stream元素打包成一个entry。在Stream的题目中,出现频率不低。

(4)One correction:在id输入框上加监听器说不是为了取得用户输入的信息,而是监听用户在输入框中有没有按回车键。如果按回车键,等同于按了login按钮,也会调用pressLogin()函数。

So far, all the in-class examples, chapter-based projects and assignment projects have been illustrated. It is time for us to do several simulated exams.

These simulated exam projects are derived from past exams. In Politecnico di Torino, there are four exam sessions every year. The majority of the exams are complicated, nevertheless, minority of the exams are simple enough to get full marks.

The most complicated exam project ever completed by me is“Schedule”. And this is the exact reason why I would like to choose this one to post in my Wechat public account.

本项目要求编一个程序来排大学课程表,不仅要指明上课的时间,还有上课的教室。所有需要编写代码的类都放在timetablepackage中,主的类是Schedule,其他类都是辅助的类。

最后一行字非常值得我们注意一下,JDK documentation指的是API Java libraries,也就是所有已经定义好的库类、函数。但是在考试的时候呢,翻开JDK documentation去引经据典是非常浪费时间的事情。又因为考试是开卷的,所以强烈建议各位宝宝在考试前就把资料整理好。

在排课之前,必须先把教室和时间块定义好。接下来,我们先看应该如何把教室加入到系统中。newRoom()函数接收两个参数,创建Room类的实例,并且把object references加入到Schedule类的某个数据结构中。

newRoom()函数接收到的参数都是用来创建Room类实例的,所以Room类的constructor接收这些参数,并且存为attributes。

getRooms()函数的返回值是所有教室的ids的列表,并且按照字母顺序排列。getSeatsInRoom()函数的返回值是某一个给定教室的座位数量。

关于教室的需求到此为止,现在我们来分析一下,Schedule类中存放Room类实例的数据结构应该是怎样的?虽然没有explicitly说id of the room具有unique性质,但是id of the room应该是具有unique性质的,所以适合使用Map/ Set。又因为需要按照id of the room排序,所以本黄鸭认为采用TreeMap是最好的;否则用TreeSet的话,还要为Room类定义比较方法。

getRooms()函数使用了Stream的方法,一般来说,Stream都要等到后面几个requirements才会粉墨登场。那么,我们能不能先用keyset()函数先对付一下呢?答案是不行,因为keyset()函数的返回值是Set类型的,不是List类型的。

getSeatsInRooms()函数使用的是cascading dotted notation,并非Stream的方法。

接下来是time slot的定义方法,这是本项目的第一个大难点。如果这里没有编出来,那么JUnit test最多只能通过requirement 1.1 and 1.2,可想而知,根本不可能及格。

defineSlots()函数接受三个参数,创建Slot类的实例,并且把object references都存放在Schedule类的某个数据结构中。请各位宝宝重点看一下这三个参数:

(1)Start time,第一个slot开始的时间,同时也是一天开始上课的时间。

(2)Length in minutes,每节课的长度。

(3)Number of slots,每天最多有多少节课。

下面是几个例子:

有了这三个参数,再假设课间不下课,我们可以计算:

(1)每节课开始和结束的时间。

(2)最后一个slot结束的时间,即每天最晚放学时间。

(3)etc

Schedule class中的defineSlots()非常简单,只要把参数传递给Slot类的constructor就行了。

另外,listSlots attribute的属性是“protected static”,这有些奇特,说明在同一个package中有其他类想要直接访问这个变量,我们会在其他requirement中遇到这样的情况。

listSlots()函数的返回值是所有的slots的字符串表达。果然,我们要用编程的方法把每节课什么时候开始、什么时候结束都算出来。假设课间不下课,那么每节课开始的时间是:

“The current number of slot”应该是一个变量,从1增加到“number of slots”。又因为start time单位不统一,不仅有12进制的小时,还有60进制的分钟,做加减乘除四则运算非常困难,所以本黄鸭决定先把小时全部转化为分钟,再计算。

在constructor中,start time的单位被换算为分钟。在attribute中,不仅存放了start time的小时分钟表示法,还存放了转化为分钟的表示法。

用allSlotStartTimeMinutes()函数可以计算出每节课开始的时间。For循环可以让“index”的值从增加到number of slots,并把它带入上文总结出的递推公式中。

toListString()函数的重要性是二十颗五角星,重点中的重点是for each循环,遍历存放每节课开始时间的ArrayList。这个函数中有三个变量:

那么,不是第一节课的开始时间是怎么赋予变量“temp”的呢?因为没有下课时间,所以在前一次执行for each循环体的时候,就是在处理上一节课信息的时候,上节课的下课时间就是下节课的开始时间。

在把start time/ end time的单位从分钟化为“XX小时XX分钟”时,反斜线“/”表示整除,百分号“%”表示取余。本黄鸭一开始也不知道这两个简单的符号就能实现单位换算,还是借鉴了网上的代码才编出来的。

另外,作为返回值的字符串格式必须是“hh:mm - hh:mm”,即所有的数字都必须是两位数。类似的需求在大作业中有遇到过,调用String.format()函数就能实现。

最后,Slot类中的toListString()函数的返回值类型是List,与Schedule类的listSlots()函数的返回值类型相同。所以,我们既可以在listSlots()函数中直接调用/返回toListString()函数;也可以把toListString()函数的结果展开,用collector整理为List,再返回。

欢迎使用本黄鸭编写的小程序~

微信公众号二维码:

你的每一个“好看”,都是对我的鼓励

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190117G0XKX200?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券