using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace st_hw06
{
public partial class Form1 : Form
{
Label[] lbl_Input;
TextBox[] txt_Input;
Object3D[] ObjectList = new Object3D[100];
string[] material = { "Al", "Cu", "Fe", "Pb" };
public Form1()
{
InitializeComponent();
InitialInputTxt();
}
private void InitialInputTxt() //將輸入介面編成陣列,方便修改
{
lbl_Input = new Label[] { lbl_Length, lbl_Height};
txt_Input = new TextBox[] { txt_Length, txt_Height};
}
private void cmb_Shape_SelectedIndexChanged(object sender, EventArgs e)
{
ChangeVisible();
}
//陣列內容依序代表: 球體, 正方體, 圓柱體, 金字塔體
bool[,] visibleTable = { { true, false }, { true, false }, { true, true }, { true, true } };
string[,] lbl_Input_txt = { { "半徑", "" }, { "邊長", "" }, { "半徑", "高" }, { "邊長", "高" } };
private void ChangeVisible() //改變輸入介面
{
int index = cmb_Shape.SelectedIndex;
for (int i = 0; i < lbl_Input.Length; i++)
{
lbl_Input[i].Visible = visibleTable[index, i];
txt_Input[i].Visible = visibleTable[index, i];
lbl_Input[i].Text = lbl_Input_txt[index, i];
}
}
private void btn_Add_Click(object sender, EventArgs e)
{
int SelectMaterial = cmb_Material.SelectedIndex;
int SelectShape = cmb_Shape.SelectedIndex;
if ((SelectMaterial < 0) || (SelectShape < 0))
MessageBox.Show("ERROR!!");
else
{
double Parameter1 = 0, Parameter2 = 0;
if (txt_Length.Text != "")
Parameter1 = Convert.ToDouble(txt_Length.Text);
if (txt_Height.Text != "")
Parameter2 = Convert.ToDouble(txt_Height.Text);
switch (cmb_Shape.SelectedIndex)
{
case 0:
ObjectList[Object3D.Amount] = new Ball(SelectMaterial, Parameter1);
txt_BallNum.Text = Ball.Amount.ToString();
break;
case 1:
ObjectList[Object3D.Amount] = new Cube(SelectMaterial, Parameter1);
txt_CubeNum.Text = Cube.Amount.ToString();
break;
case 2:
ObjectList[Object3D.Amount] = new Cylinder(SelectMaterial, Parameter1, Parameter2);
txt_CylinderNum.Text = Cylinder.Amount.ToString();
break;
case 3:
ObjectList[Object3D.Amount] = new Pyramid(SelectMaterial, Parameter1, Parameter2);
txt_PyramidNum.Text = Pyramid.Amount.ToString();
break;
default:
MessageBox.Show("ERROR!!");
break;
}
}
}
private void btn_Calculate_Click(object sender, EventArgs e)
{
lvi_Result.Items.Clear();
ShowResult();
}
private void ShowResult()
{
for (int i = 0; i < Object3D.Amount; i++)
{
string ObjectShape = ObjectList[i].GetType().Name;
//欄位名稱:形狀
ListViewItem ObjectData = new ListViewItem(ObjectList[i].ObjectName);
//欄位名稱:材質
ObjectData.SubItems.Add(ObjectList[i].Material);
//欄位名稱:密度
ObjectData.SubItems.Add(ObjectList[i].Density.ToString());
//欄位名稱:邊長/半徑
if ((ObjectShape == "Ball") || (ObjectShape == "Cylinder"))
ObjectData.SubItems.Add(ObjectList[i].Radius.ToString());
else ObjectData.SubItems.Add(ObjectList[i].Length.ToString());
//欄位名稱:高
if ((ObjectShape == "Ball") || (ObjectShape == "Cube"))
ObjectData.SubItems.Add("N/A"); //球與正方體沒有高
else ObjectData.SubItems.Add(ObjectList[i].Height.ToString());
//欄位名稱:體積
ObjectData.SubItems.Add(ObjectList[i].CalVolume().ToString());
//欄位名稱:重量
ObjectData.SubItems.Add(ObjectList[i].CalWeight().ToString());
lvi_Result.Items.Add(ObjectData);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace st_hw06
{
class Object3D
{
protected static double PI = 3.1415926;
protected static double[] density = { 2.7, 8.9, 7.9, 11.34 }; //依序: 鋁,銅,鐵,鉛
protected static string[] material = { "Al", "Cu", "Fe", "Pb" };
protected static int amount = 0;
protected string objectName = null;
protected int materialType;
protected double length = 0;
protected double height = 0;
protected double radius = 0;
public double Density
{
get { return density[materialType]; }
}
public string Material
{
get { return material[materialType]; }
}
public static int Amount
{
get { return amount; }
}
public string ObjectName
{
get { return objectName; }
}
public virtual double Length
{
get { return length; }
}
public virtual double Height
{
get { return height; }
}
public virtual double Radius
{
get { return radius; }
set { radius = value; }
}
//建構子
public Object3D(int materialType)
{
this.materialType = materialType;
amount++;
}
public virtual double CalVolume()
{
return 0;
}
public virtual double CalWeight()
{
return 0;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace st_hw06
{
class Cube : Object3D
{
new private static int amount = 0;
//建構子
public Cube(int material, double length):base(material)
{
objectName = "正方體";
this.length = length;
amount++;
}
new public static int Amount
{
get { return amount; }
}
public override double Length
{
get { return length; }
}
public static Cube Create(int material, double length)
{
Cube cube = null;
if ((material < 0) || (length < 0))
return cube;
else
{
cube = new Cube(material, length);
return cube;
}
}
public override double CalVolume()
{
return length * length * length;
}
public override double CalWeight()
{
return Density * CalVolume();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace st_hw06
{
class Ball : Object3D
{
new private static int amount = 0;
public Ball(int material, double radius):base(material)
{
objectName = "球體";
this.radius = radius;
amount++;
}
new public static int Amount
{
get { return amount; }
}
public override double Radius
{
get { return radius; }
}
public static Ball Create(int material, double length)
{
Ball ball = null;
if ((material < 0) || (length < 0))
return ball;
else
{
ball = new Ball(material, length);
return ball;
}
}
public override double CalVolume()
{
return (4.0 / 3.0) * radius * radius * radius;
}
public override double CalWeight()
{
return Density * CalVolume();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace st_hw06
{
class Cylinder : Object3D
{
new private static int amount = 0;
public Cylinder(int material, double radius, double height):base(material)
{
objectName = "圓柱體";
this.radius = radius;
this.height = height;
amount++;
}
new public static int Amount
{
get { return amount; }
}
public override double Radius
{
get { return radius; }
}
public override double Height
{
get { return height; }
}
public override double CalVolume()
{
return PI * radius * radius * height;
}
public override double CalWeight()
{
return Density * CalVolume();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace st_hw06
{
class Pyramid : Object3D
{
new private static int amount = 0;
public Pyramid(int material, double length, double height):base(material)
{
objectName = "金字塔體";
this.length = length;
this.height = height;
amount++;
}
new public static int Amount
{
get { return amount; }
}
public override double Length
{
get { return length; }
}
public override double Height
{
get { return height; }
}
public override double CalVolume()
{
return length * length * height/3.0;
}
public override double CalWeight()
{
return Density * CalVolume();
}
}
}
第8組
回覆刪除Shape3D裡面存了很多參數(lenght,radius....等)但有些子類別會使用不到,是否考慮加入在子類別內會更好 ?
同第8組的看法,因為這樣反而是讓父類別涵括了所有子類別的欄位,雖然程式看起來比較簡短,但感覺不符合繼承原有的初衷。另外,金字塔的體積計算公式好像有點問題?
回覆刪除會選擇這樣做是為了滿足介面,讓使用Object3D宣告成的陣列也能印出length,radius,height這些參數.
刪除有想過也能在一開始就先宣告陣列,再輸入資料同時記錄參數,但是這樣太浪費空間.
後來第八組的朋友有跟我說可以看看你們第二組用的list. 我有空會再改進.
金字塔的計算公式少除3,我現在改好放上去了.
Form1.cs 架構簡潔,非常容易辨別事件的內容!
回覆刪除LIstView 有點睛的效果!
許多 Shape 的 .cs 檔內的含有參數建構子 ( 例如:長度、半徑‧‧‧等 ),刪除後程式仍可執行。
請問於子類別撰寫參數建構子有任何用途嗎? (若只是練習為目的就不再此討論範疇內
謝謝囉!
刪除原本在父類別Object3D.cs裡面沒有加入對邊長,半徑那些欄位作存取的屬性. 後來就如上面回答到的,想要試試看在listview那邊連邊長,半徑這些一開始輸入的資料都能印出來,所以才又在Object3D.cs裡面加入虛擬的屬性,讓每個形狀的子類別能夠在介面靠父類別的陣列呼叫出自己獨有的欄位.(類似像在把父類別包含的東西廣泛化,最後輸出時在去判斷父類別陣列存的是哪個子類別,然後再去呼叫那個子類別獨有的東西. 不然只靠原本的父類別無法連邊長、半徑那些都抓出來. 但是這樣似乎也和物件導向的概念有點脫節,因為父類別不該擁有子類別獨有的東西,而現在把父類別擁有的東西廣泛化,那所佔的記憶體就會更大.)
不過因為目前的版本中,父類別的虛擬屬性有寫出return邊長、半徑那些欄位,和子類別的覆寫屬性的內容相同,所以才會覺得把子類別內寫的屬性刪掉也沒關係. 如果原本父類別的虛擬屬性作的只是初始化,沒有實際return我們要的東西,像是
public virtual double Length()
{
get {return 0.0;} //類似只做初始化,真正需要處理存取時再由子類別的屬性去做
}
這個時候,如果把子類別的override屬性刪掉,那form1.cs: ShowResult()呼叫到的ObjectData.SubItems.Add(ObjectList[i].Length.ToString())就只會執行父類別的虛擬屬性. 這樣實際執行後,cube的邊長顯示就一直是0.