oop课程4-6次作业小结

oop · 浏览次数 : 0

小编点评

前言 第四次题目集主要是对答题判断程序3的进一步改进,增加了对题目类的拆分,需要使用继承的方式来实现各个种类的题目之间的联系,但是难度不是很大,只需要对答题程序3稍作修改,区别各个Question的内部实现,既多选与填空的判题方法等,还是很好修改的。此外还有两个有关迭代的小题目,不是很难但是让我了解了对toString方法的使用,这些都对后续的题目具有启发作用,是从答题判断程序到家庭电路系统的过度,能够让我们更能适应新题面的到来。 设计与分析 第四次作业(答题判题程序-4)  新增多选和填空类,并将所有接收题目信息的方法全部移入Submission类中,类间关系更新为如下新增多选类  按题目要求,增加多选类,主要继承和重写了题目类的判题方法,具体实现为:  for循环遍历所有提交的答案,如果有与题目中某一个正确答案相同的选项,则设标志flag为true,如果遍历结束flag仍为false则证明所有答案都不符合,函数返回值0,代表所有选项都不匹配,答案错误。在遍历结束后,判断提交答案的数组长度是否小于正确答案的数组长度,如果为真,则证明提交的答案不全,函数返回2,代表半对。如果为假,则提交答案长度正好符合正确答案长度,且全部正确,即答案完全正确,函数返回1新增填空类  按题目要求,增加填空类,主要继承和重写了题目类的判题方法,具体实现如下:public int check(String fillAns) { if(fillAns.matches(\"\\\\s*\"))return 0;//无答案判错,与测试点无关 if(this.fillAns.matches(\".*\"+fillAns.trim()+\".*\")) { if(this.fillAns.equals(fillAns.trim())) { return 1; } return 2; } else return 0; }如果提交答案存在于正确答案中,则继续判断是否完全相同,相同则函数返回1,代表答案完全正确,否则返回2,代表部分正确,再否则则返回0,代表答案错误。第五次作业(家居强电电路模拟程序-1)本次作业为第一次家庭电路的模拟,是一次全新项目的开始,题目要求模拟计算家庭220V电路下的设备电压,实现各种电路设备之间的串并联联系,可设置控制设备和受控设备两种设备,使它们都继承自电路设备类。类间关系设计如下: Element类  根据题目要求,设计所有电路设备的父类如下: abstract class Element implements Comparable<Element> { int id; String inPin; String outPin; Boolean inUsed; Boolean outUsed; double inVolt; double outVolt; public abstract String getInPin(); public abstract String getOutPin(); public abstract Boolean getInUsed(); public abstract Boolean getOutUsed(); public abstract void setInPin(String inPin); public abstract void setOutPin(String outPin); public abstract char getType();} Element类中包含输入引脚和输出引脚,储存另一个电路设备的引脚信息,在之后根据连接信息查找和搜索。并储存了每个引脚的电压,以便计算每个电路设备的电压信息。  Element类中包含抽象方法getType(),在排序方法compareTo()中调用,可以根据给定的顺序排序所有Element的实例,具体实现如下:public int compareTo(Element o) { String order = \"KFLRBD\"; if(getType()==o.getType()) return id-o.id; return order.indexOf(getType())-order.indexOf(o.getType()); }  根据下标索引相减,可以大量减少排序方法的代码块,使用父类的抽象方法,能够极大缩减函数复用带来的不必要重复。还可以根据给定顺序排序,即使顺序更改,只需要修改一处便可适应新排序。  与getType()相似,Element类中还包含toString()方法,子类定义时,便重写该方法,使得最后输出时只需要短短一个for循环遍历输出,直接使用System.out.println(e);即可输出。

正文

(1)前言

`
  第四次题目集主要是对答题判断程序3的进一步改进,增加了对题目类的拆分,需要使用继承的方式来实现各个种类的题目之间的联系,但是难度不是很大,只需要对答题程序3稍作修改,区别各个Question的内部实现,既多选与填空的判题方法等,还是很好修改的。此外还有两个有关迭代的小题目,不是很难但是让我了解了对toString方法的使用,这些都对后续的题目具有启发作用,是从答题判断程序到家庭电路系统的过度,能够让我们更能适应新题面的到来。
  第五次题目集揭开了全新题面的大幕,面对智能家居的到来,我们也需要适应新潮流,针对家庭电路的控制进行模拟,本次主要进行了抽象类的实际使用,将电路中所有的电路设备进行抽象,所有的共同属性都归为一个大类,储存了各种状态和方法,在之后进行继承与调用。只要确定好了方向,对于各个类的定义就自然会成型,测试点不难,很容易就能过,因为是第一次迭代,不用考虑得太多,只要能够实现大致的功能就够了,但是一定要在开始就确定好方向,不然很容易跌进思维陷阱。
  第六次题目集对第一次的家庭电路系统进行了第一次修改,增加了串联和并联类,从只有一条简单串联电路更新到了存在多条串联和并联电路,并使并联类关联到串联类,并联多条单独的串联类,类间关系更加复杂,电压的计算更加多变。

(2)设计与分析

`

第四次作业(答题判题程序-4)

  新增多选和填空类,并将所有接收题目信息的方法全部移入Submission类中,类间关系更新为如下
Alt
Alt

新增多选类

  按题目要求,增加多选类,主要继承和重写了题目类的判题方法,具体实现为:
  for循环遍历所有提交的答案,如果有与题目中某一个正确答案相同的选项,则设标志flag为true,如果遍历结束flag仍为false则证明所有答案都不符合,函数返回值0,代表所有选项都不匹配,答案错误。在遍历结束后,判断提交答案的数组长度是否小于正确答案的数组长度,如果为真,则证明提交的答案不全,函数返回2,代表半对。如果为假,则提交答案长度正好符合正确答案长度,且全部正确,即答案完全正确,函数返回1

新增填空类

  按题目要求,增加填空类,主要继承和重写了题目类的判题方法,具体实现如下:

public int check(String fillAns)
    {
        if(fillAns.matches("\\s*"))return 0;//无答案判错,与测试点无关
        if(this.fillAns.matches(".*"+fillAns.trim()+".*"))
        {
            if(this.fillAns.equals(fillAns.trim()))
            {
                return 1;
            }
            return 2;
        }
        else return 0;
    }

如果提交答案存在于正确答案中,则继续判断是否完全相同,相同则函数返回1,代表答案完全正确,否则返回2,代表部分正确,再否则则返回0,代表答案错误。

第五次作业(家居强电电路模拟程序-1)

本次作业为第一次家庭电路的模拟,是一次全新项目的开始,题目要求模拟计算家庭220V电路下的设备电压,实现各种电路设备之间的串并联联系,可设置控制设备和受控设备两种设备,使它们都继承自电路设备类。类间关系设计如下:
Alt

Element类

  根据题目要求,设计所有电路设备的父类如下:

abstract class Element implements Comparable<Element>
{
    int id;
    String inPin;
    String outPin;
    Boolean inUsed;
    Boolean outUsed;
    double inVolt;
    double outVolt;

    public abstract String  getInPin();
    public abstract String  getOutPin();
    public abstract Boolean getInUsed();
    public abstract Boolean getOutUsed();
    public abstract void setInPin(String inPin);
    public abstract void setOutPin(String outPin);
    public abstract char getType();
}

  类中包含输入引脚和输出引脚,储存另一个电路设备的引脚信息,在之后根据连接信息查找和搜索。并储存了每个引脚的电压,以便计算每个电路设备的电压信息。

  Element类中包含抽象方法getType(),在排序方法compareTo()中调用,可以根据给定的顺序排序所有Element的实例,具体实现如下:

public int compareTo(Element o)
  {
      String order = "KFLRBD";
      if(getType()==o.getType())
          return id-o.id;
      return order.indexOf(getType())-order.indexOf(o.getType());
  }

  根据下标索引相减,可以大量减少排序方法的代码块,使用父类的抽象方法,能够极大缩减函数复用带来的不必要重复。还可以根据给定顺序排序,即使顺序更改,只需要修改一处便可适应新排序。

  与getType()相似,Element类中还包含toString()方法,子类定义时,便重写该方法,使得最后输出时只需要短短一个for循环遍历输出,直接使用System.out.println(e);即可输出。

控制设备

开关#

public void changeState()
{
    state ^= 1;
}

  最简单的控制设备,只有0和1两种状态,在切换状态时可以使用异或运算简化方法体。

分档调速器#

  比开关多两个状态,设有position代表档位(0~3),因为档位连续,可用数组存储每个档位的调速数据,设立私有数据域private final double[] gradeTimes = {0,0.3f,0.6f,0.9f};,在每次调速之后,用档位对应下标,提取数据域中对应档位的值,更新调速数据。

受控设备

白炽灯#

  根据题目要求,白炽灯的亮度随电压差呈线性变化,可求出方程式为L = 50 + (V-10) / 1.4,且电压超过220和低于0时电压不再变化,可写出获取亮度的方法如下:

public double getLighting()
{
    double volt = getAbsVolt();
    if(volt<=9)return 0;
    else if(volt>=220)return 200;
    else return 50 + (volt-10) / 1.4;
}

日光灯#

  根据题意,电压不为0时亮度恒为180,否则亮度为0。获取电压的方法可简化为一个三目运算符volt == 0 ? 0 : 180

吊扇#

  与白炽灯相似,吊扇的转速与电压差呈正比,可写出获取转速的方法如下:

public double getSpeed()
{
    double volt = getAbsVolt();
    if(volt<80)return 0;
    else if(volt>150)return 360;
    else return 80 + 4.0 * (volt-80);
}

计算电压(家庭电路类)

  最初设计时,考虑到题目给出各个引脚的数据,所以我在Element类中储存了引脚的数据,记录下了各个引脚通向的另一个引脚,于是在计算电压的部分也利用了这部分数据,根据引脚的连通情况去进行搜索,每搜索到一个电器的同时去计算它的电压情况,计算好电压后,各个电器会在最后输出阶段自动调用已经写好的方法,计算出需要输出的数据。
  可是如何去遍历搜索却成为了一个难题,在一开始我便想得太复杂了,想着储存了引脚的数据,就一定要用上,可是越往后做越发现,引脚的数据在这次迭代中根本用不到,其实删除这部分数据的输入捕获,也能够做到全对,可是考虑到之后可能会用,便仍接着遍历搜索的思路去写了。
  在计算电压之前,先遍历找出VCC引脚接在了哪个用电器上,并从该用电器作为出发点开始搜索计算。给出VCC所在的引脚和接入的电路设备,如果引脚为1,则将2引脚电压更新,并将该引脚和与它连接的电路设备加入到队列q中,然后进行下一次遍历,反之依然。如果队列q中没有电路设备,则循环结束,如此搜索完一遍,便可以将所有引脚的电压都计算出来,在得到所有引脚的电压之后,便可以用电压差计算出每个设备的电压。由于我写的太过繁琐,就不展示出来了。大家可以自己去尝试写一下。

第六次作业(家居强电电路模拟程序-2)

Alt

Element类

  看到本次题面,我发现引脚还是没有被用上,于是我一怒之下怒了一下,把引脚直接给删除了(),Element类被修改为如下:

abstract class Element implements Comparable<Element>
{
    int id;
    double voltage;
    double resistance;//电阻
    final double EPS = 1e-10;
    final double INF = Double.POSITIVE_INFINITY;//1.78e+308
    abstract boolean canGo(Element e);
    public void updateVolt(double wholeResistance,double wholeVolt)
    {
        voltage = resistance * wholeVolt / wholeResistance;
    }
    public double getVolt()
    {
        return Math.abs(voltage);
    }
    public abstract char getType();
    @Override
    public int compareTo(Element o)
    {
        String order = "KFLBRDAHS";
        if(getType()==o.getType())
            return id-o.id;
        return order.indexOf(getType())-order.indexOf(o.getType());
    }
}

  由于本次迭代考虑了电阻,于是我将电阻的数据直接存放在Element类中,方便直接调用。考虑到电路断路电阻为无穷大,我又在类中放了一个final类型的数据INF代表无穷大,在电路断路时方便直接设置,并且该无穷大直接使用Double类中的无穷大,意为真正的无穷大。既然Double类中已经实现好了,自然要偷这个懒。并且类中还存放了另一个final类型的数据EPS,电压电阻等数据为Double类型,计算时需要考虑精度问题,需要时可方便直接调用。
  在经过几轮思考之后,Element中还新增了一个canGo的抽象方法,返回该电路设备是否能让电流通过,对于所有的开关,canGo根据闭合状态返回是否可通过;对于所有用电器,直接返回true,即使在之后要考虑电压过大用电器会烧断,也可以直接在该方法中修改返回值;对于所有串联电路,只要电路中有一个元件的canGo方法返回了false,便直接返回false。对于并联电路也同样可以这样思考,这便是根据实际情况,使用递归运算简化了代码的复杂度。

Light类

  抽象出所有灯的父类Light,由于所有灯都有亮度的数据,并且输出时结构相似,于是在Light类中添加抽象方法getLighting(),并将所有灯的输出方法放在Light类中,如此一来,便又一次降低了代码量,增加了方法的复用度。

abstract class Light extends Electric
{
    public abstract double getLighting();
    @Override
    public String toString()
    {
        return "@"+getType()+id+":"+String.format("%.0f",Math.floor(getLighting()));
    }
}

Fan类

  与Light类似,本次添加了一种风扇,风扇种类便从1变为了2,所以可以抽象出Fan类,同样具有所有风扇类都有的转速属性,并且输出结构类似,于是添加抽象方法getSpeed()toString()方法

abstract class Fan extends Electric
{
    public abstract double getSpeed();
    @Override
    public String toString()
    {
        return "@"+getType()+id+":"+String.format("%.0f",Math.floor(getSpeed()));
    }
}

(3)采坑心得

  由于考虑了引脚之间的连接,题目被我想得复杂化了,因此修改了很久都不对,太过复杂的连通关系总是把我绕进去,改却总又改不对,最后还是要简化,所以在一开始构思的时候不能想得太复杂,一切都要从简,然后才去慢慢深入修改。
  还有就是一定要通篇检查代码,不要自以为某一段没有问题就不去检查,因为家庭电路系统-1题面中要求到要对电路设备进行排序,而答案提交之后也顺利通过了,所以在第二次迭代中我就没去检查这段代码,以至于一直修改其他地方分数却保持不变,直到最后才开始怀疑。

(4)改进建议

  在之后的迭代中,我希望能够引脚的部分重新加回来,但是不需要通过太复杂的代码或是对代码整体重新修改,就像是上面说的,不用一开始就想得复杂,而在之后通过打补丁的方式加入功能。也希望之后无论添加什么功能,都能轻易修改好,随后仅剩一点点的调试。

(5)总结

  抽象是步入java大门的一把利器,不仅在家庭电路模拟中,也能用在各个场景中。面向抽象编程,不需要在一开始就将功能全部设想到,而是利用抽象的特性,一步步具象化,这样不仅代码清晰,每一步需要考虑的东西也减少了,将一次不能够完成的功能分布展开,能够在让自己在每一步迭代中清晰的知道自己在这一次要完成什么,也能让自己写代码的效率提高。
  总的来说,这三次题目集又让我学到了很多,希望之后的迭代不会超出我代码的可变范围。希望自己对代码的掌控更加熟练。

与oop课程4-6次作业小结相似的内容:

oop课程4-6次作业小结

目录(1)前言(2)设计与分析第四次作业(答题判题程序-4)新增多选类新增填空类第五次作业(家居强电电路模拟程序-1)Element类控制设备开关#分档调速器#受控设备白炽灯#日光灯#吊扇#计算电压(家庭电路类)第六次作业(家居强电电路模拟程序-2)Element类Light类Fan类(3)采坑心得

OOP课第三阶段总结

OOP课第三阶段总结 前言: 我想说的第一句是:”我感受到了设计上的极大缺陷“,从一开始,我完全就忽略了引脚的存在。因为在第二阶段中,家电模拟大作业一、二在不需要考虑引脚的情况下也可以完成。但是当来到第三次,出现了互斥开关,因为互斥开关的特殊性,它具有1、2、3三个引脚,并且连接方式多种多样,所以再

OOP课第二阶段总结

OOP课第二阶段总结 前言 作为第二次3+1的总结,明显感受到了此次题目集越来越复杂,结合了实际的物理知识来解决现实中的电路问题。因为电路可以一直扩展下去,情况千变万化,难以像上次题目集一样找到一个呆板的做法。这次题目集,让很多人连题目都无法理解,代码也是无从下手,因为这些人根本不知道如何去设计,如

OOP第二阶段题集总结

一.前言 知识点:考察继承和多态为多,其中还涉及迭代器的使用,在每个题集中都有一个综合性题目设计多方面知识点考试,有List类和HashMap的使用以及正则表达式的运用,并且注重考查设计,理解类与类之间的关系进行合理设计,其中也要遵循我们所学的单一职责,开闭原则,迪米特法则等。 题量:第四次题集和第

深入理解 C++ 中的多态与文件操作

C++ 多态 多态(Polymorphism)是面向对象编程(OOP)的核心概念之一,它允许对象在相同操作下表现出不同的行为。在 C++ 中,多态通常通过继承和虚函数来实现。 理解多态 想象一个场景,你有一个动物园,里面有各种动物,如猫、狗、鸟等。每个动物都有自己的叫声。使用面向对象编程,我们可以创

C++ 多级继承与多重继承:代码组织与灵活性的平衡

C++ 多级继承 多级继承是一种面向对象编程(OOP)特性,允许一个类从多个基类继承属性和方法。它使代码更易于组织和维护,并促进代码重用。 多级继承的语法 在 C++ 中,使用 : 符号来指定继承关系。多级继承的语法如下: class DerivedClass : public BaseClass1

7.0 Python 面向对象编程

python是一种面向对象的编程语言,面向对象编程(Object-Oriented Programming,OOP)是一种编程思想,其核心概念是“对象”。对象是指一个具有特定属性和行为的实体,而面向对象编程就是通过对这些实体进行抽象、分类、封装和继承等操作,来实现程序的结构和逻辑。在python中,我们可以通过定义类、创建实例和调用方法等方式,来实现面向对象编程的思想,从而编写出更加灵活、可扩展、

[转帖]JVM 系列 - 内存区域

一、对象在JVM中的表示: OOP-Klass模型 https://www.jianshu.com/p/424a920771a3 写的很赞。 注意:OOP-Klass是hotspot的JVM实现原理,其他JVM的实现可能不一样。、 OOP表示java实例,Klass表示class。 Klass: 包

Netty-介绍-1

Netty介绍和应用场景 要求 已经掌握了 主要技术构成: Java OOP 编程、 Java 多线程编程、 Java IO 编程 、 Java 网络编程、 常用的Java 设计模式(比如 观察者模式 ,命令模式,职责链模式 )、 常用的数据结构(比如 链表) Netty的介绍 1、Netty 是由

继承,super,重写,多态,抽象,接口

继承,super,重写,多态,抽象,接口 继承 extends 用于表示两个类之间的继承关系,继承是OOP的四大特性之一,他允许一个类(称之为子类或派送类) 继承另一个类(称之为父类或基类)的变量和方法,子类可以复用父类的方法和变量,也可以添加和覆盖父类的方法和变量 extends的基本语法 使用e