软件构造blog2--基于类继承和多态的Shapes程序及GUI
(一)前言
在软件构造课上学习到上面两页ppt的时候,我有一个大胆的想法。
据我们所知,对于正方形和长方形来讲,两者有明显的继承关系,在代码实现方面会简便的很多。那么如果对更多的图形呢,况且老师上习题课已经讲过GUI,我联想起了之前看到过的一个空缺shapes类,这次我把它的代码补齐。
(二)类设计
其实对于刚刚学习java或者oop的小白,怎么去理解抽象类呢。不讲那些难懂的定义,我的理解是,就像你们班级内的人,虽然属性各不相同,但是你们班级是一样的。
那么我们就先写一个抽象类。
package shapes;
import java.awt.Graphics;
public abstract class Shape {
public abstract void draw(Graphics g);
public abstract int calc(Graphics g);//计算周长的虚方法
public abstract int cals(Graphics g);//计算面积的虚方法
}
draw是我一会要用来画图的方法,另外两个一个求周长,一个求面积。如果你对类的继承和多态很熟悉的话,override这两个方法这部分代码会非常地容易。
(1) Circle 圆
古人就讲圆滑,做人做事儿不能太有棱角,适当的时候,圆可以让你滚的更远。实际上大家都会觉得圆这种图形最简单,就用一个半径就可以描述。但是,不要忘了,影响他位置的还有圆心坐标。
package shapes;
import java.awt.Graphics;
public class Circle extends Shape {
private int x;
private int y;
private int radius;
public Circle(int x, int y, int radius)
{
this.x = x;
this.y = y;
this.radius = radius;
}
@Override
public void draw(Graphics g) {
g.drawOval(x-radius, y-radius, radius*2, radius*2);
}
@Override
public int calc(Graphics g) {
return (int) (Math.PI*radius*2);//求周长,c=2*π*r
}
@Override
public int cals(Graphics g) {
return (int) (Math.PI*radius*radius);//求面积,s=π*r*r;
}
}
(2) Ellipse
细心的读者们发现了为啥就这个类没标记中文名?在大学生涯中,英语是很重要的,不然软件构造的ppt有可能看不懂。
椭圆,四个元素,实际上每种图形需要几个元素,你可以通过查阅draw的API来判断,当时我就是看到drawoval内有四个参数,才反应过来应该是四个元素。
package shapes;
import java.awt.Graphics;
public class Ellipse extends Shape {
private int x;
private int y;
private int longaxis;
private int shortaxis;
public Ellipse(int x, int y, int longaxis,int shortaxis)
{
this.x = x;
this.y = y;
this.longaxis = longaxis;
this.shortaxis=shortaxis;
}
@Override
public void draw(Graphics g) {
g.drawOval(x, y, longaxis, shortaxis);
}
@Override
public int calc(Graphics g) {
return (int) (Math.PI*2*shortaxis+4*(longaxis-shortaxis));//求周长,周长公式是google的不知道对不对
}
@Override
public int cals(Graphics g) {
return (int) (Math.PI*longaxis*shortaxis);//求面积,s=π*a*b
}
}
(3) Line 直线
毫无疑问,起点终点的横纵坐标作为参数。
package shapes;
import java.awt.Graphics;
public class Line extends Shape {
private int x1;
private int y1;
private int x2;
private int y2;
public Line(int x1, int y1, int x2, int y2)
{
this.x1 = x1; this.y1 = y1;
this.x2 = x2; this.y2 = y2;
}
@Override
public void draw(Graphics g) {
g.drawLine(x1, y1, x2, y2);
}
@Override
public int calc(Graphics g) {
int x=x2-x1;
int y=y2-y1;
return (int) Math.sqrt(x^2+y^2);//求周长,勾股定理
}
@Override
public int cals(Graphics g) {//求面积,没有面积
return 0;
}
}
(4) Rectangle 矩形
drawRect有xy长宽四个元素,xy具体坐标表示哪个点我有点忘了,应该是中心点。
package shapes;
import java.awt.Graphics;
public class Line extends Shape {
private int x1;
private int y1;
private int x2;
private int y2;
public Line(int x1, int y1, int x2, int y2)
{
this.x1 = x1; this.y1 = y1;
this.x2 = x2; this.y2 = y2;
}
@Override
public void draw(Graphics g) {
g.drawLine(x1, y1, x2, y2);
}
@Override
public int calc(Graphics g) {
int x=x2-x1;
int y=y2-y1;
return (int) Math.sqrt(x^2+y^2);//求周长,勾股定理
}
@Override
public int cals(Graphics g) {//求面积,没有面积
return 0;
}
}
(5) Triangle 三角形
三个点的坐标,也就是六个元素,但是求周长和面积累死我了,有更好的算法请私信我呜呜呜。
package shapes;
import java.awt.Graphics;
public class Triangle extends Shape {
private int[] x = new int[3];
private int[] y = new int[3];
public Triangle(int x1, int y1, int x2, int y2, int x3, int y3)
{
x[0] = x1; x[1] = x2; x[2] = x3;
y[0] = y1; y[1] = y2; y[2] = y3;
}
@Override
public void draw(Graphics g) {
g.drawPolygon(x, y, x.length);
}
@Override
public int calc(Graphics g) {
return (int) (Math.sqrt((x[0]-x[1])^2+(y[0]-y[1])^2)+Math.sqrt((x[2]-x[1])^2+(y[2]-y[1])^2)+Math.sqrt((x[0]-x[2])^2+(y[0]-y[2])^2));//求周长,此为三角形关于三边坐标的周长公式
}
@Override
public int cals(Graphics g) {
return Math.abs(x[0]*y[1]+x[1]*y[2]+x[2]*y[0]-x[0]*y[2]-x[1]*y[0]-x[2]*y[1]);//求面积,Google的三角形三边坐标的面积
}
}
(6) Square 正方形
Square理所应当的继承了矩形的优良品质,而且周长面积公式都很清晰。
package shapes;
import java.awt.Graphics;
public class Square extends Shape
{
private int x;
private int y;
private int len;
public Square(int x,int y,int len)
{
this.x=x;
this.y=y;
this.len=len;
}
@Override
public void draw(Graphics g) {
g.drawRect(x, y, len, len);
}
@Override
public int calc(Graphics g) {//求周长,周长等于4*边长
return 4*len;
}
@Override
public int cals(Graphics g) {//求面积,面积等于边长的平方
return len^2;
}
}
(7) Picture 图类
picture类中我写了add,draw等实现方法,要把图形画出来。不多说,大家自己体会。
package shapes;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Picture extends JFrame {
private static final long serialVersionUID = 1L;
private int width;
private int height;
private ArrayList<Shape> listShape = new ArrayList<Shape>();
private class ShapesPanel extends JPanel {
private static final long serialVersionUID = 1L;
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for ( Shape s : listShape )
{
s.draw(g);
}
}
}
public void add(Shape s)
{
listShape.add(s);
}
public Picture(int width, int height)
{
add(new ShapesPanel());
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.width = width;
this.height = height;
}
public void draw()
{
setLocationRelativeTo(null);
setSize(width, height);
setVisible(true);
}
}
(8) Mypic 主函数
最后弄一个main类,尝试在一个图里画出很多图形。
package shapes;
public class MyPic {
public static void main(String[] args)
{
Picture pic = new Picture(420,300);
Circle c1 = new Circle(320,40,80);
Rectangle r1 = new Rectangle(100, 100, 100,100);
Triangle t1 = new Triangle(100, 100, 200, 100, 150, 50);
Line l1 = new Line(0,205,400,205);
Circle c2 = new Circle(200,200,50);
Square s1 =new Square(0,0,100);
Ellipse e1=new Ellipse(0,0,100,50);
pic.add(c1);
pic.add(r1);
pic.add(t1);
pic.add(l1);
pic.add(c2);
pic.add(s1);
pic.add(e1);
pic.draw();
System.out.println(c1.calc(null));//输出c1周长
System.out.println(r1.calc(null));//输出r1周长
System.out.println(t1.calc(null));//输出t1周长
System.out.println(l1.calc(null));//输出l1周长
System.out.println(c2.calc(null));//输出c2周长
System.out.println(s1.calc(null));//输出s1周长
System.out.println(e1.calc(null));//输出e1周长
System.out.println(c1.cals(null));//输出c1面积
System.out.println(r1.cals(null));//输出r1面积
System.out.println(t1.cals(null));//输出t1面积
System.out.println(l1.cals(null));//输出l1面积
System.out.println(c2.cals(null));//输出c2面积
System.out.println(s1.cals(null));//输出s1面积
System.out.println(e1.cals(null));//输出e1面积
}
}
(三)结果
咱也实在没啥艺术细菌,本来想画个小房子的,结果烟囱和太阳画成这个鬼样子,唉。
(四)总结
其实思路很简单,在做完lab123之后再看这个,简直没什么动脑的地方,可能就是在复写周长和面积的时候复杂一点。
不过还是发扬光大了类继承和多态的思想,很好的小练习。