チャンゲー言語における拡張機能の実装方法と設計思想について詳細に解説します。型の機能追加やインターフェース実装の仕組み、パッケージ間でのインポート・エクスポートルールを具体的なコード例とともに説明します。
1. 拡張の基本概念
チャンゲーではextendキーワードを使用して既存の型に新機能を追加できます。このメカニズムは以下の特徴を持ちます:
- 型の定義を変更せずに機能を追加
- メンバー変数の追加は不可
- アクセス修飾子(public/protected/private)の制約あり
- スーパークラスのメンバー参照不可
1.1 拡張の種類
| 種類 | 特徴 |
|---|---|
| 直接拡張 | 単純なメソッド追加 |
| インターフェース拡張 | インターフェース実装を追加 |
2. 直接拡張の実装
2.1 基本構文
extend String {
public func 文字列長表示() {
println("文字列長: ${this.size}")
}
}
2.2 修飾子の使用
拡張メンバーには以下の修飾子を指定できます:
public: 全域からアクセス可能protected: 現在のパッケージとサブクラスprivate: 拡張内でのみ利用static: タイプ経由でのみアクセスmut: 構造体メンバーの変更許可
2.3 ジェネリック型への拡張
class Container<T> {
var data: T
}
// 特定型への拡張
extend Container<Int64> {
public func 倍化() {
data = data * 2
}
}
// ジェネリックパラメータ付き拡張
extend<T> Container<T> where T <: Comparable<T> {
public func 等価確認(other: Container<T>) -> Bool {
return this.data.equals(other.data)
}
}
3. インターフェース拡張
3.1 基本構文
interface 計算可能<T> {
func 加算(other: T) -> T
}
extend Vector2 <: 計算可能<Vector2> {
public func 加算(other: Vector2) -> Vector2 {
return Vector2(x: this.x + other.x, y: this.y + other.y)
}
}
3.2 複数インターフェースの実装
interface 描画可能 { func 描画() }
interface 移動可能 { func 移動(dx: Int64, dy: Int64) }
extend Rectangle <: 描画可能 & 移動可能 {
public func 描画() { ... }
public func 移動(dx: Int64, dy: Int64) { ... }
}
4. パッケージ間のインポート・エクスポート
4.1 隠しインポートの仕組み
チャンゲーでは拡張は以下のルールでインポートされます:
- 型をインポートすれば自動的に関連拡張も利用可能
- インターフェース拡張は対応するインターフェースもインポート必要
- パッケージ外へのエクスポートは厳格な制限あり
4.2 オーファンルール
インターフェース拡張は以下の条件を満たす必要があります:
// 有効な例
// パッケージa
public class ロガー {}
// パッケージb
public interface ロギング {
func ログ(message: String)
}
// パッケージa内で実装
extend ロガー <: ロギング { ... }
4.3 ジェネリック拡張の導入
interface シリアライズ可能 {
func シリアライズ() -> String
}
extend<T> Pair<T, T> <: シリアライズ可能 where T <: シリアライズ可能 {
public func シリアライズ() -> String {
return "(${first.シリアライズ()}, ${second.シリアライズ()})"
}
}
5. 実践的な応用例
5.1 標準ライブラリ拡張
extend String {
public func カメル変換() -> String {
var result = ""
var capitalize = false
for c in this {
if c == '_' {
capitalize = true
} else {
if capitalize {
result.append(c.大文字())
capitalize = false
} else {
result.append(c)
}
}
}
return result
}
}
5.2 第三者ライブラリ拡張
interface データベース保存可能 {
func 保存() -> Bool
}
extend ThirdPartyModel <: データベース保存可能 {
public func 保存() -> Bool {
return this.内部保存()
}
}
5.3 計算プロパティの追加
extend Int64 {
public prop 素数確認: Bool {
get() {
if this <= 1 { return false }
for i in 2..=sqrt(this) {
if this % i == 0 { return false }
}
return true
}
}
}