public abstract class PartBase : Space { #region 基本屬性 /// <summary> /// 是否復合板 /// </summary> public bool IsCladPart { get; set; } /// <summary> /// 基層密度(kg/L) /// </summary> public double BaseDensity { get; set; } /// <summary> /// 復層密度(kg/L) /// </summary> public double CladDensity { get; set; } /// <summary> /// 基層材料 /// </summary> public string BaseMaterial { get; set; } /// <summary> /// 復層材料 /// </summary> public string CladMaterial { get; set; } /// <summary> /// 零件類型 /// </summary> public PartType PartType { get; set; } #endregion 基本屬性 #region 控件屬性 public TextBox TbBaseDensity { get; set; } public TextBox TbCladDensity { get; set; } public TextBox TbBaseMaterial { get; set; } public TextBox TbCladMaterial { get; set; } public CheckBox CbxIsCladPart { get; set; } #endregion 控件屬性 #region 控件事件,由於是抽象類,需要在繼承類中實現其事件 public virtual void TbDensity_Validating(object sender, CancelEventArgs e) { "未實現【密度】的虛方法!".showAlert(); } public virtual void TbCladMaterial_Validating(object sender, System.ComponentModel.CancelEventArgs e) { "未實現【復層材料】的虛方法!".showAlert(); } public virtual void TbBaseMaterial_Validating(object sender, System.ComponentModel.CancelEventArgs e) { "未實現【基層材料】的虛方法!".showAlert(); } public virtual void CbxIsCladPlate_CheckedChanged(object sender, EventArgs e) { "未實現【是否復合板】的虛方法!".showAlert(); } #endregion 控件事件,由於是抽象類,需要在繼承類中實現其事件 public PartBase() { } /// <summary> /// 繼承腔體類中的屬性值 /// 並且設置下一級類中的屬性值 /// </summary> /// <param name="v"></param> /// <param name="s"></param> public PartBase(Vessel v, Space s) : base(v, s) { } }
繼承抽象類的下一級普通類需要:
1.重寫抽象類A中的虛事件。
2.賦值A中屬性便於向下傳遞。
3.本類B中的屬性值需要通過類實例b傳遞到下一級屬性中。
4.普通類B必須要有一個代表類實例的屬性b,便於在本類中進行值的儲存。比如,驗證TextBox中用戶輸入的數值,如果值可以接受的話可以存儲在b屬性中。
5.在下級類實例化構造過程中傳值給此實例屬性b。
public class ShellBase : PartBase { #region 公用屬性 /// <summary> /// 殼體名義厚度 /// </summary> protected string zShellTn; /// <summary> /// 殼體名義厚度 /// </summary> public string ShellTn { get { return zShellTn; } set { zShellTn = value; if (IsCladPart) { if (value.Contains("+")) { TnBase = double.Parse(value.Split('+')[0]); TnClad = double.Parse(value.Split('+')[1]); Tn = TnBase + TnClad; } else { } } else if (!string.IsNullOrEmpty(value)) { if (value.Contains("+")) { } else { double tn = 0; double.TryParse(value, out tn); Tn = tn; } } } } /// <summary> /// 殼體公稱厚度 /// </summary> public double Tn { get; set; } /// <summary> /// 是否為外徑基准 /// </summary> public bool IsBasedOnOD { get; set; } /// <summary> /// 殼體公稱直徑 /// </summary> public double ShellDn { get; set; } /// <summary> /// 基層厚度 /// </summary> public double TnBase { get; set; } /// <summary> /// 復層板厚 /// </summary> public double TnClad { get; set; } /// <summary> /// 當前類的一個實例,用於記錄驗證時的值,重要,它是一個傳值橋梁 /// </summary> public ShellBase Shell { get; set; } #endregion 公用屬性 #region 幾何屬性 /// <summary> /// 體積 /// </summary> public double Volume { get; set; } /// <summary> /// 內表面積 /// </summary> public double InnerArea { get; set; } /// <summary> /// 外表面積 /// </summary> public double OuterArea { get; set; } /// <summary> /// 質量 /// </summary> public double Mass { get; set; } #endregion 幾何屬性 #region 控件屬性 public CheckBox CbxIsBasedOnOD { get; set; } public TextBox TbShellDn { get; set; } public TextBox TbShellTn { get; set; } public Label LblVolume { get; set; } public Label LblMass { get; set; } public Label LblInnerArea { get; set; } public Label LblOutterArea { get; set; } #endregion 控件屬性 #region 控件事件 private void TbShellTn_Validating(object sender, System.ComponentModel.CancelEventArgs e) { if (TbShellTn.Text == "") { ErrShow.Clear(); return; } if (IsCladPart) { List<double> lst = TbShellTn.getCladPlateThickness(); Shell.ShellTn = TbShellTn.Text; if (lst.Count > 1) { Shell.TnBase = lst[0]; Shell.TnClad = lst[1]; Shell.Tn = TnBase + TnClad; ErrShow.Clear(); } else { ErrShow.SetError(TbShellTn, "請按復合板的厚度【50+4.5】的格式填寫!"); e.Cancel = true; } } else { Shell.TnBase = TbShellTn.getNumber(); Shell.Tn = TnBase; Shell.ShellTn = TbShellTn.Text; ErrShow.Clear(); } } private void TbShellDn_Validating(object sender, System.ComponentModel.CancelEventArgs e) { if (TbShellDn.Text == "") { ErrShow.Clear(); return; } double dn = 0; double.TryParse(TbShellDn.Text, out dn); if (dn > 20) { Shell.ShellDn = dn; ErrShow.Clear(); } else { ErrShow.SetError(TbShellDn, "輸入的數據有誤!"); e.Cancel = true; } } private void CbxIsBasedOnOD_CheckedChanged(object sender, EventArgs e) { Shell.IsBasedOnOD = CbxIsBasedOnOD.Checked; } /// <summary> /// 重寫抽象類中的方法 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public override void CbxIsCladPlate_CheckedChanged(object sender, EventArgs e) { Shell.IsCladPart = CbxIsCladPart.Checked; } public override void TbDensity_Validating(object sender, CancelEventArgs e) { TextBox tb = (TextBox)sender; if (tb.Text == "") { if (tb == TbBaseDensity) { Shell.BaseDensity = 0; } else { Shell.CladDensity = 0; } ErrShow.Clear(); return; } double midu = 0; double.TryParse(tb.Text, out midu); if (midu > 1 && midu < 30) { if (tb == TbBaseDensity) { Shell.BaseDensity = midu; } else { Shell.CladDensity = midu; } ErrShow.Clear(); } else { ErrShow.SetError(tb, "密度輸入有問題!"); e.Cancel = true; } } public override void TbCladMaterial_Validating(object sender, System.ComponentModel.CancelEventArgs e) { Shell.CladMaterial = TbCladMaterial.Text; } public override void TbBaseMaterial_Validating(object sender, System.ComponentModel.CancelEventArgs e) { Shell.BaseMaterial = TbBaseMaterial.Text; } #endregion 控件事件 public ShellBase() { } public ShellBase(Vessel V, Space S) : base(V, S) { } /// <summary> /// 繼承腔體類中的屬性值 /// 並且設置下一級類中的屬性值 /// </summary> /// <param name="V"></param> /// <param name="S"></param> public ShellBase(Vessel V, Space S, ShellBase SB) : base(V, S) { //傳值 Shell = SB; #region 控件賦值 //PartBase if (SB.CbxIsCladPart != null) { CbxIsCladPart = SB.CbxIsCladPart; } if (SB.TbBaseDensity != null) { TbBaseDensity = SB.TbBaseDensity; } if (SB.TbCladDensity != null) { TbCladDensity = SB.TbCladDensity; } if (SB.TbBaseMaterial != null) { TbBaseMaterial = SB.TbBaseMaterial; } if (SB.TbCladMaterial != null) { TbCladMaterial = SB.TbCladMaterial; } //ShellBase if (SB.CbxIsBasedOnOD != null) { CbxIsBasedOnOD = SB.CbxIsBasedOnOD; } if (SB.TbShellDn != null) { TbShellDn = SB.TbShellDn; } if (SB.TbShellTn != null) { TbShellTn = SB.TbShellTn; } #endregion 控件賦值 #region 屬性傳值 IsBasedOnOD = SB.IsBasedOnOD; ShellDn = SB.ShellDn; Tn = SB.Tn; ShellTn = SB.ShellTn; TnBase = SB.TnBase; TnClad = SB.TnClad; #endregion 屬性傳值 #region 通過將SB賦值給本類中屬性Shell,用Shell來接收控件驗證時得到的參數值,然后傳值到下一個繼承者 //賦值是從抽象類中來的 IsCladPart = SB.IsCladPart; BaseDensity = SB.BaseDensity; CladDensity = SB.CladDensity; BaseMaterial = SB.BaseMaterial; CladMaterial = SB.CladMaterial; #endregion 通過將SB賦值給本類中屬性Shell,用Shell來接收控件驗證時得到的參數值,然后傳值到下一個繼承者 } /// <summary> /// 在底層使用時進行調用,必須在控件賦值后進行使用,否則無效 /// </summary> public void ShellSetting() { #region 上一個抽象類中的控件 if (TbBaseDensity != null) { TbBaseDensity.Validating -= TbDensity_Validating; TbBaseDensity.Validating += TbDensity_Validating; } if (TbCladDensity != null) { TbCladDensity.Validating -= TbDensity_Validating; TbCladDensity.Validating += TbDensity_Validating; } if (TbBaseMaterial != null) { TbBaseMaterial.Validating -= TbBaseMaterial_Validating; TbBaseMaterial.Validating += TbBaseMaterial_Validating; } if (TbCladMaterial != null) { TbCladMaterial.Validating -= TbCladMaterial_Validating; TbCladMaterial.Validating += TbCladMaterial_Validating; } if (CbxIsCladPart != null) { CbxIsCladPart.CheckedChanged -= CbxIsCladPlate_CheckedChanged; CbxIsCladPart.CheckedChanged += CbxIsCladPlate_CheckedChanged; } #endregion 上一個抽象類中的控件 #region 本類中的控件 if (TbShellDn != null) { TbShellDn.Validating -= TbShellDn_Validating; TbShellDn.Validating += TbShellDn_Validating; } if (TbShellTn != null) { TbShellTn.Validating -= TbShellTn_Validating; TbShellTn.Validating += TbShellTn_Validating; } if (CbxIsBasedOnOD != null) { CbxIsBasedOnOD.CheckedChanged -= CbxIsBasedOnOD_CheckedChanged; CbxIsBasedOnOD.CheckedChanged += CbxIsBasedOnOD_CheckedChanged; } #endregion 本類中的控件 } }
6.再下一級的類C中只需要管好自己類中屬性的向下傳遞即可。
public class HeadBase : ShellBase { #region 屬性設置 /// <summary> /// 封頭類型 /// </summary> protected HeadType zHeadType; /// <summary> /// 封頭類型 /// </summary> public HeadType HeadType { get { return zHeadType; } set { zHeadType = value; } } /// <summary> /// 封頭最小厚度 /// </summary> protected double ztmin; /// <summary> /// 封頭最小厚度 /// </summary> public double tmin { get { return ztmin; } set { ztmin = value; } } /// <summary> /// 封頭標准,程序中直接設置 /// </summary> protected string zHeadStandard; /// <summary> /// 封頭標准,程序中直接設置 /// </summary> public string HeadStandard { get { return zHeadStandard; } set { zHeadStandard = value; } } /// <summary> /// 封頭直邊 /// </summary> protected double zh; /// <summary> /// 封頭直邊 /// </summary> public double h { get { return zh; } set { zh = value; } } #endregion #region 控件屬性 public TextBox TbTmin { get; set; } public TextBox TbHeadStandard { get; set; } public TextBox Tbh { get; set; } #endregion 控件屬性 #region 控件事件 /// <summary> /// 在下一級的實例中執行數據驗證 /// </summary> public void HeadSetting() { if (Tbh != null) { Tbh.Validating += Tbh_Validating; } if (TbTmin != null) { TbTmin.Validating += TbTmin_Validating; } if (TbHeadStandard != null) { TbHeadStandard.Validating += TbHeadStandard_Validating; } } private void TbHeadStandard_Validating(object sender, System.ComponentModel.CancelEventArgs e) { HeadStandard = TbHeadStandard.Text; } private void TbTmin_Validating(object sender, System.ComponentModel.CancelEventArgs e) { if (TbTmin.Text == "") { ErrShow.Clear(); return; } double val = 0; double.TryParse(TbTmin.Text, out val); if (val <= 0) { ErrShow.SetError(TbTmin, "封頭最小厚度應大於0"); e.Cancel = true; } else if (Tn > 0) { if (val > Tn) { ErrShow.SetError(TbTmin, "封頭最小厚度應小於公稱厚度"); e.Cancel = true; } else { tmin = val; ErrShow.Clear(); } } else { tmin = val; ErrShow.Clear(); } } private void Tbh_Validating(object sender, System.ComponentModel.CancelEventArgs e) { if (Tbh.Text == "") { ErrShow.Clear(); return; } double val = 0; double.TryParse(Tbh.Text, out val); if (val < 25) { ErrShow.SetError(Tbh, "封頭直邊應大於等於25mm"); e.Cancel = true; } else { h = val; ErrShow.Clear(); } } #endregion 控件事件 public HeadBase() { } /// <summary> /// /// </summary> /// <param name="V"></param> /// <param name="S"></param> /// <param name="SB"></param> public HeadBase(Vessel V, Space S, ShellBase SB) : base(V, S, SB) { } /// <summary> /// 繼承容器類中的屬性值 /// 繼承腔體類中的屬性值 /// 並且設置下一級類中的屬性值 /// </summary> /// <param name="V"></param> /// <param name="S"></param> /// <param name="HB"></param> public HeadBase(Vessel V, Space S, ShellBase SB, HeadBase HB) : base(V, S, SB) { #region 控件繼承 if (HB.Tbh!=null) { Tbh = HB.Tbh; } if (HB.TbTmin != null) { TbTmin = HB.TbTmin; } if (HB.TbHeadStandard != null) { TbHeadStandard = HB.TbHeadStandard; } #endregion 控件繼承 #region 屬性傳值 h = HB.h; tmin = HB.tmin; HeadStandard = HB.HeadStandard; #endregion 屬性傳值 } #region 錐形封頭公用函數 public double wConeInArea(double Di, double Dis, double ang) { double angH = ang.DegreeToRadian(); double L = (Di / 2 - Dis / 2) / angH.SinH(); return ((Math.PI * L * (Di / 2 + Dis / 2)) * 1e-6).Round(2); } public double xConeVolume(double Di, double h1, double Dis, double h2, double R, double r, double ang, double tn) { double angH = ang.DegreeToRadian(); double a = angH.SinH() / 4; double b = (angH.SinH() * angH.CosH() + angH) / 2 - angH.SinH(); double c = 2 * angH.SinH() - Math.Pow(angH.SinH(), 3) / 3 - angH.SinH() * angH.CosH() - angH; double d = Math.PI * (a * Di * Di * R + b * Di * R * R + c * Math.Pow(R, 3)); double e = (Math.Pow(Di - 2 * R * (1 - angH.CosH()), 3) - Math.Pow(Dis + 2 * (1 - angH.CosH()) * (r + tn), 3)) * Math.PI / (24 * Math.Tan(angH)); double f = Math.PI * (a * Dis * Dis * (r + tn) - b * Dis * Math.Pow(r + tn, 2) + c * Math.Pow(r + tn, 3)); double g = Math.PI * Di * Di * h1 / 4; double i = Math.PI * Dis * Dis * h2 / 4; return ((d + e + f + g + i) * 1e-9).Round(3); } #endregion 錐形封頭公用函數 }
7.再下級類D中也只需要管好自己類中屬性的向下傳遞即可,本例中沒有其它屬性。
此類無關緊要,如果有也同“下級類”,此處省略。
8.調用類中應注意各實例的先后與賦值情況,否則容易導致出錯。
public partial class Test1 : Form { Vessel V = null; Space S = null; ShellBase SB = null; HeadBase HB = null; HeadEllipseBase HEB = null; public Test1() { InitializeComponent(); } private void Test1_Load(object sender, EventArgs e) { V = new Vessel(); V.ErrShow = errShow; S = new Space(V); SB = new ShellBase(V, S); //凡是抽象類中的屬性必須在其繼承的類的實例中賦值才可以用 #region 控件賦值 SB.TbBaseDensity = tbBaseDensity; SB.TbCladDensity = tbCladDensity; SB.TbBaseMaterial = tbBaseMaterial; SB.TbCladMaterial = tbCladMaterial; SB.CbxIsCladPart = cbxIsCladPart; //ShellBase //而當前類的屬性則也直接在其實例中進行賦值 SB.CbxIsBasedOnOD = cbxIsBasedOnOd; SB.TbShellDn = tbDn; SB.TbShellTn = tbTn; #endregion 控件賦值 #region 直接賦值測試 //SB.BaseDensity = 8; ////SB.CladDensity = 7; //SB.BaseMaterial = "SA-516 70"; ////SB.CladMaterial = "SA-240 316L"; //SB.IsCladPart = false; //SB.IsBasedOnOD = true; //SB.ShellDn = 1000; //SB.ShellTn = "10"; #endregion 直接賦值測試 //HeadBase HB = new HeadBase(V, S, SB); #region 控件賦值 HB.TbTmin = tbTmin; HB.TbHeadStandard = tbStandard; HB.Tbh = tbh; #endregion 控件賦值 #region 直接賦值測試 //HB.tmin = 8; //HB.HeadStandard = "GB/T 25198-2012"; //HB.h = 25; #endregion 直接賦值測試 HB.ShellSetting(); HB.HeadSetting(); } private void button2_Click(object sender, EventArgs e) { this.Close(); } private void btnCal_Click(object sender, EventArgs e) { HEB = new HeadEllipseBase(V, S, SB, HB); HEB.LblVolume = lblVolumne; HEB.LblMass = lblMass; HEB.LblInnerArea = lblInnerArea; HEB.LblOutterArea = lblOutArea; HEB.Cal(); HEB.SetResult(); } }
