執行檔的連結
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;
namespace HW6
{
public partial class Form1 : Form
{
Label[] arr_lbl_Feature;
TextBox[] arr_txt_Feature;
List Object3DList = new List();
double[] DensityTable = { 2.70, 7.90, 8.90 }; // 鋁鐵銅密度表
/******** 建構子 ********/
public Form1()
{
InitializeComponent();
arr_lbl_Feature = new Label[] { lbl_feature1, lbl_feature2 };
arr_txt_Feature = new TextBox[] { txt_feature1, txt_feature2 };
}
/******** 控制項函數 ********/
private void cmo_ObjectSelect_SelectedIndexChanged(object sender, EventArgs e)
{
ChangeVisible();
}
private void btn_Add_Click(object sender, EventArgs e)
{
ShowResult("clear");
ShowResult("starting");
// 判斷是否可以將字串轉換成數字
double[] TxtNumber = new double[arr_lbl_Feature.Length];
bool[] CanConvert = new bool[arr_lbl_Feature.Length];
bool CanCreate = false;
for (int i = 0; i < arr_lbl_Feature.Length; i++)
{
CanConvert[i] = double.TryParse(arr_txt_Feature[i].Text, out TxtNumber[i]);
}
// 建立物件
switch (cmo_ObjectSelect.SelectedIndex)
{
case 0:
if (CanConvert[0])
{
Cube ThisCube = Cube.Create(DensityTable[cmo_MaterialSelect.SelectedIndex], TxtNumber[0]);
if (ThisCube != null)
{
Object3DList.Add(ThisCube);
CanCreate = true;
}
}
break;
case 1:
if (CanConvert[0])
{
Ball ThisBall = Ball.Create(DensityTable[cmo_MaterialSelect.SelectedIndex], TxtNumber[0]);
if (ThisBall != null)
{
Object3DList.Add(ThisBall);
CanCreate = true;
}
}
break;
case 2:
if (CanConvert[0] && CanConvert[1])
{
Cylinder ThisCylinder = Cylinder.Create(DensityTable[cmo_MaterialSelect.SelectedIndex], TxtNumber[0], TxtNumber[1]);
if (ThisCylinder != null)
{
Object3DList.Add(ThisCylinder);
CanCreate = true;
}
}
break;
case 3:
if (CanConvert[0] && CanConvert[1])
{
Pyramid ThisPyramid = Pyramid.Create(DensityTable[cmo_MaterialSelect.SelectedIndex], TxtNumber[0], TxtNumber[1]);
if (ThisPyramid != null)
{
Object3DList.Add(ThisPyramid);
CanCreate = true;
}
}
break;
default:
break;
}
// 顯示建立結果
if (CanCreate)
{
ShowResult("OK");
}
else
{
ShowResult("false");
}
}
private void btn_Show_Click(object sender, EventArgs e)
{
ShowResult("clear");
ShowResult("result");
}
/******** 與前端輸入輸出相關函數 ********/
bool[,] VisibleTable = { { true, false }, { true, false }, { true, true }, { true, true } };
string[,] arr_lbl_Feature_txt = { { "邊長", "" }, { "半徑", "" }, { "半徑", "高度" }, { "邊長", "高度" } };
private void ChangeVisible()
{
int Index = cmo_ObjectSelect.SelectedIndex;
for (int i = 0; i < arr_lbl_Feature.Length; i++)
{
arr_lbl_Feature[i].Visible = VisibleTable[Index, i];
arr_txt_Feature[i].Visible = VisibleTable[Index, i];
arr_lbl_Feature[i].Text = arr_lbl_Feature_txt[Index, i];
}
}
private void ShowResult(string s)
{
switch (s)
{
case "clear": // 清空
txt_Display.Text = "";
break;
case "starting": // 顯示建立中
txt_Display.AppendText("建立中..." + Environment.NewLine);
break;
case "false": // 顯示建立失敗資訊
txt_Display.AppendText("建立失敗,請重新確認參數!" + Environment.NewLine);
break;
case "OK" : // 顯示建立成功資訊
txt_Display.AppendText("建立成功!" + Environment.NewLine);
txt_Display.AppendText("已建立的物 體數量: "+ Convert.ToString(Object3D.Amount) + Environment.NewLine);
txt_Display.AppendText("已建立的正方體數量: " + Convert.ToString(Cube.Amount) + Environment.NewLine);
txt_Display.AppendText("已建立的球 體數量: " + Convert.ToString(Ball.Amount) + Environment.NewLine);
txt_Display.AppendText("已建立的圓柱體數量: " + Convert.ToString(Cylinder.Amount) + Environment.NewLine);
txt_Display.AppendText("已建立的金字塔數量: " + Convert.ToString(Pyramid.Amount) + Environment.NewLine);
break;
case "result": // 顯示結果
txt_Display.AppendText("物體類型 體積 質量" + Environment.NewLine);
txt_Display.AppendText("----------------------------------------" + Environment.NewLine);
foreach (var element in Object3DList)
{
txt_Display.AppendText(element.ObjectType + "\t");
txt_Display.AppendText(element.Volume().ToString("F2") + "\t");
txt_Display.AppendText(element.Quality().ToString("F2"));
txt_Display.AppendText(Environment.NewLine);
}
break;
default:
break;
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HW6
{
class Object3D
{
/******** 欄位 ********/
private double density = 0;
private static int amount = 0;
private string objectType = "Object3D";
/******** 屬性 ********/
public double Density // 密度
{
get
{
return density;
}
set
{
density = value;
}
}
public static int Amount // 數量
{
get
{
return amount;
}
}
public string ObjectType // 類型(讀)
{
get
{
return objectType;
}
}
protected string ObjectType_Write // 類型(寫)
{
set
{
objectType = value;
}
}
/******** 建構子 ********/
protected Object3D()
{
amount++;
}
protected Object3D(double density)
{
this.density = density;
amount++;
}
/******** 方法 ********/
public virtual double Volume() // 計算體積
{
return 0.0;
}
public double Quality() // 計算質量
{
return Density * Volume();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HW6
{
class Cube : Object3D
{
/******** 欄位 ********/
private double side = 0;
private static int amount = 0;
/******** 屬性 ********/
public double Side // 邊長
{
get
{
return side;
}
set
{
if (value > 0)
{
side = value;
}
}
}
public new static int Amount // 數量
{
get
{
return amount;
}
}
/******** 建構子 ********/
public Cube( ) : base()
{
ObjectType_Write = "Cube ";
amount++;
}
private Cube(double density, double side)
: base(density)
{
Side = side;
ObjectType_Write = "Cube ";
amount++;
}
/******** 方法 ********/
public override double Volume()
{
return Side * Side * Side;
}
public static Cube Create(double density, double side)
{
if ((density < 0) || (side < 0))
{
return null;
}
else
{
return new Cube(density, side);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HW6
{
class Ball : Object3D
{
/******** 欄位 ********/
private double radius = 0;
private static int amount = 0;
public const double pi = 3.1415926;
/******** 屬性 ********/
public double Radius // 邊長
{
get
{
return radius;
}
set
{
if (value > 0)
{
radius = value;
}
}
}
public new static int Amount // 數量
{
get
{
return amount;
}
}
/******** 建構子 ********/
public Ball()
: base()
{
ObjectType_Write = "Ball ";
amount++;
}
private Ball(double density, double radius)
: base(density)
{
Radius = radius;
ObjectType_Write = "Ball ";
amount++;
}
/******** 方法 ********/
public override double Volume()
{
return 4.0 * pi * Radius * Radius * Radius / 3.0;
}
public static Ball Create(double density, double radius)
{
if ((density < 0) || (radius < 0))
{
return null;
}
else
{
return new Ball(density, radius);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HW6
{
class Cylinder : Object3D
{
/******** 欄位 ********/
private double radius = 0;
private double height = 0;
private static int amount = 0;
public const double pi = 3.1415926;
/******** 屬性 ********/
public double Radius // 半徑
{
get
{
return radius;
}
set
{
if (value > 0)
{
radius = value;
}
}
}
public double Height // 高度
{
get
{
return height;
}
set
{
if (value > 0)
{
height = value;
}
}
}
public new static int Amount // 數量
{
get
{
return amount;
}
}
/******** 建構子 ********/
public Cylinder()
: base()
{
ObjectType_Write = "Cylinder";
amount++;
}
private Cylinder(double density, double radius, double height)
: base(density)
{
Radius = radius;
Height = height;
ObjectType_Write = "Cylinder";
amount++;
}
/******** 方法 ********/
public override double Volume()
{
return pi * Radius * Radius * Height;
}
public static Cylinder Create(double density, double radius, double height)
{
if ((density < 0) || (radius < 0) || (height < 0))
{
return null;
}
else
{
return new Cylinder(density, radius, height);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HW6
{
class Pyramid : Object3D
{
/******** 欄位 ********/
private double side = 0;
private double height = 0;
private static int amount = 0;
/******** 屬性 ********/
public double Side // 邊長
{
get
{
return side;
}
set
{
if (value > 0)
{
side = value;
}
}
}
public double Height // 高度
{
get
{
return height;
}
set
{
if (value > 0)
{
height = value;
}
}
}
public new static int Amount // 數量
{
get
{
return amount;
}
}
/******** 建構子 ********/
public Pyramid()
: base()
{
ObjectType_Write = "Pyramid ";
amount++;
}
private Pyramid(double density, double side, double height)
: base(density)
{
Side = side;
Height = height;
ObjectType_Write = "Pyramid ";
amount++;
}
/******** 方法 ********/
public override double Volume()
{
return Side * Side * Height / 3.0;
}
public static Pyramid Create(double density, double side, double height)
{
if ((density < 0) || (side < 0) || (height < 0))
{
return null;
}
else
{
return new Pyramid(density, side, height);
}
}
}
}
第8組
回覆刪除檢驗是否可以轉換的Code以及VisibleTable等顯示格子的code寫的太好了。
尤其是轉換數字的code,在做視窗程式的時候最容易發生資料轉換錯誤的問題了,受益良多
林高遠評論:
回覆刪除優
1. 看到這個我才知道switch case也可以用字串
2. 張貼程式碼選擇性開啟做得實在太棒了!閱讀起來很舒服
缺
1. ObjectType 與 ObjectTypeWrite怎麼不寫成同一個屬性
2. 基礎類別的體積和質量最好不要實做,因為"形狀"是沒有體積和質量可言的,"正方體"或"球"才有;實做出來,呼叫錯了也難發現
3. pi宣告在基礎類別較好,因為這是共通特性
4. ObjectType_Write = "Ball "; 應該在宣告欄位直接初始化解決就好,因為看起來這行是建構就一定會發生
針對缺點的部分,我加以說明一下:
回覆刪除1. ObjectType 與 ObjectTypeWrite: 這種奇怪的寫法主要是因為需要的存取權限不同的結果,存的部分是protected,取是public。不過其實後來發現是可以寫在一起的,所以這邊的確是可以改進。
2. 沒錯,基礎類別是不應該被實體化的,不過既然還沒教,這邊也暫時不這麼做。
3. 這點其實我在寫的時候是有點猶豫的,就如你所說的它畢竟是常數,不受各種類別影響而放在基礎類別上,但又不是所有衍生類別都用得到(譬如說: 方塊),而是等需要使用的時候再涵蓋進來就好了,因此才會變成你看到的結果。
4. 這點我就比較不贊成了。雖然衍生類別的ObjectType的存放的內容是不一樣的,但它們的型態是一樣且皆為必須的(都是string),所以基於繼承精神而在基礎類別上先建立欄位型態(只是順便放Object3D),等衍生類別的物件建立時再填入正確的內容"Ball"。另外這樣的方式可以藉由ObjectType讀取衍生類別的物件的資訊。
我覺得你改回在我下面的"回覆",然後把這篇刪掉比較好,這樣問答的脈絡才明確
刪除