断面の数が増えてくると、共通の処理が増えてくる。
例えば、断面によらない単位質量、断面二次半径の算出やアドインでの出力単位の処理など。
これらで共通部分の処理は共通に書くことができるように、鉄骨断面の基底クラスを作成し、
SecBuildHやSecBuildBoxに継承させてコードの簡略化をはかる。
ただし、前に話題にした通り、数値計算の実装部分に関しては、引数を数字のみにした静的メソッドとする。
基底クラスの処理
基底クラスはあらかじめ作っていたSecSteelを使うことにする。
厳密にいうと、StbSecSteelは断面を表しているデータではない(どちらかというと断面リストを表している)ので対応の上では少々違和感があるかもしれないが、わかりやすさ重視でこのままにする。
SecSteelには各断面性能を返すメソッドを実装する。
断面形状によって異なる断面積や断面二次モーメントについては、継承先で実装するものとする。
こういったときはabstructをつけたくなるが、抽象メソッドは抽象クラスの中にしか作れないらしい。
SecSteelを抽象クラスにしてしまうと、共通の処理の実装ができなくなってしまうので、ルールとして実装してね、とするしかないかな。
sec/steel.ts
export class SecSteel { /** * 断面積 * @returns 断面積 */ area(): number { throw new Error("このメソッドは未実装です"); } //略 /** * 単位質量 * @returns 単位質量 */ massPerMetre(): number { return SecSteel.massPerMetre(this.area()); } //略 /** * 断面性能 * @param propertyType 出力する断面性能のタイプ * @returns 断面性能 */ property(propertyType: SecPropertyType): number { switch (propertyType) { case SecPropertyType.Area: return this.area(); case SecPropertyType.ElasticModulusY: return this.elasticModulusY(); case SecPropertyType.ElasticModulusZ: return this.elasticModulusZ(); case SecPropertyType.MassPerMetre: return this.massPerMetre(); case SecPropertyType.RadiusOfGyrationY: return this.radiusOfGyrationY(); case SecPropertyType.RadiusOfGyrationZ: return this.radiusOfGyrationZ(); case SecPropertyType.SecondMomentOfAreaY: return this.secondMomentOfAreaY(); case SecPropertyType.SecondMomentOfAreaZ: return this.secondMomentOfAreaZ(); default: throw new Error("実装していない断面性能タイプです"); } } //略 }
SecSteelのところで実装するのは、単位質量、断面二次半径、タイプ指定による断面性能。これでちょっと書くのが面倒なswitch分岐を書く回数を減らせた。
継承クラスの処理
継承先のSecBuildHとSecBuildBoxでは、断面積、断面二次モーメントをオーバーライドさせる。
最初に話したように数値計算は静的メソッドとしているので、それを呼び出す形となる。 sec/build-h.ts
** * 組立H形鋼 */ export class SecBuildH extends SecSteel { //略 /** * 断面積 * @returns 断面積 */ area() { return SecBuildH.area(this.a, this.b, this.t1, this.t2); } //略 }
インスタンスメソッドは増えているので行数自体は大幅には減らないが、見た目はすっきりした。
SecSteelを鉄骨断面の基底クラスとして、処理を簡略化 · st-func/st-func-ts@b32259c · GitHub
アドインの処理
ライブラリの変更処理を実装する。
出力単位の処理やプロパティタイプの処理はSecSteelを引数にもった関数で実施し、SecBuildHなどの関数では、インスタンスを作りそれに投げるだけとした。
functions.ts
function getSecSteelProperty(propertyType: string, section: SecSteel): number { const propertyTypeEnum = toSecPropertyType(propertyType); const value = section.property(propertyTypeEnum); return Unit.output(value, unitOfSecProperty(propertyTypeEnum)); } /** * 組立角形鋼管の断面性能。 * @customfunction secBuildBox secBuildBox * @param propertyType 表示したい断面性能のタイプ * @param a 成 A * @param b 幅 B * @param t1 成方向の板厚 t1 * @param t2 幅方向の板厚 t2 * @returns 断面性能 */ export function secBuildBox(propertyType: string, a: number, b: number, t1: number, t2: number): number { const secBuildBox: SecBuildBox = new SecBuildBox(); secBuildBox.setDimensions(Unit.input(a, "mm"), Unit.input(b, "mm"), Unit.input(t1, "mm"), Unit.input(t2, "mm")); return getSecSteelProperty(propertyType, secBuildBox); }
断面性能関数で計算時に鉄骨断面クラスのインスタンスを渡す仕様に変更 · st-func/st_func_addin@b937b7e · GitHub
これで、断面タイプを増やすのが簡略化されたので、今後もう少し断面タイプを増やしていきたい。