第13章 モジュールと名前空間
13.1 名前空間/Namespace
PHP
<?php
// 名前空間の宣言(ファイルの先頭)
namespace App\Models;
class User {
public string $name;
}
// 別の名前空間
namespace App\Services;
use App\Models\User;
class UserService {
public function getUser(): User {
return new User();
}
}
// 完全修飾名
$user = new \App\Models\User();
// use でエイリアス
use App\Models\User as UserModel;
// 関数と定数のインポート
use function App\Helpers\formatDate;
use const App\Config\MAX_SIZE;
// グループ use(PHP 7.0+)
use App\Models\{User, Post, Comment};
use App\Services\{
UserService,
PostService as PS
};
TypeScript
// 名前空間(非推奨、モジュールを推奨)
namespace App {
export namespace Models {
export class User {
name: string = "";
}
}
export namespace Services {
export class UserService {
getUser(): Models.User {
return new Models.User();
}
}
}
}
// 使用
const user = new App.Models.User();
// 名前空間のマージ
namespace App {
export namespace Utils {
export function log(message: string): void {
console.log(message);
}
}
}
App.Utils.log("Hello");
VB.NET
' 名前空間の宣言
Namespace App.Models
Public Class User
Public Property Name As String
End Class
End Namespace
Namespace App.Services
Public Class UserService
Public Function GetUser() As Models.User
Return New Models.User()
End Function
End Class
End Namespace
' 使用(別ファイル)
Imports App.Models
Imports App.Services
Module Program
Sub Main()
Dim user As New User()
Dim service As New UserService()
End Sub
End Module
' エイリアス
Imports UserModel = App.Models.User
' 完全修飾名
Dim user2 As New App.Models.User()
' グローバル名前空間
Dim list As New Global.System.Collections.Generic.List(Of Integer)
13.2 モジュールシステム
PHP(Composer/PSR-4)
<?php
// composer.json
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
// src/Models/User.php
namespace App\Models;
class User {
// ...
}
// src/Services/UserService.php
namespace App\Services;
use App\Models\User;
class UserService {
public function createUser(): User {
return new User();
}
}
// index.php
require_once 'vendor/autoload.php';
use App\Services\UserService;
$service = new UserService();
TypeScript(ES Modules)
// models/user.ts
export class User {
constructor(public name: string) {}
}
export interface UserData {
name: string;
email: string;
}
// 名前付きエクスポート
export const MAX_USERS = 100;
// デフォルトエクスポート
export default class DefaultExport {}
// services/userService.ts
import { User, UserData, MAX_USERS } from './models/user';
import DefaultExport from './models/user';
// エイリアス
import { User as UserModel } from './models/user';
// すべてインポート
import * as Models from './models/user';
const user = new Models.User("John");
// 再エクスポート
export { User } from './models/user';
export * from './models/user';
export * as Models from './models/user';
// 型のみインポート
import type { UserData } from './models/user';
// 動的インポート
async function loadModule() {
const module = await import('./models/user');
return new module.User("John");
}
VB.NET(アセンブリとモジュール)
' プロジェクト参照による依存関係管理
' .vbproj
<ItemGroup>
<ProjectReference Include="..\MyLibrary\MyLibrary.vbproj" />
</ItemGroup>
' NuGet パッケージ参照
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
' Models/User.vb
Namespace Models
Public Class User
Public Property Name As String
End Class
End Namespace
' Services/UserService.vb
Imports MyProject.Models
Namespace Services
Public Class UserService
Public Function CreateUser() As User
Return New User()
End Function
End Class
End Namespace
' Program.vb
Imports MyProject.Services
Module Program
Sub Main()
Dim service As New UserService()
End Sub
End Module
' 友好アセンブリ(internal を公開)
' AssemblyInfo.vb
<Assembly: InternalsVisibleTo("MyProject.Tests")>
13.3 パッケージ管理
PHP(Composer)
# 初期化
composer init
# パッケージのインストール
composer require monolog/monolog
# 開発用パッケージ
composer require --dev phpunit/phpunit
# パッケージの更新
composer update
# インストール(composer.lock に従う)
composer install
// composer.json
{
"name": "vendor/project",
"require": {
"php": ">=8.0",
"monolog/monolog": "^3.0"
},
"require-dev": {
"phpunit/phpunit": "^10.0"
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
TypeScript(npm/yarn/pnpm)
# 初期化
npm init
# パッケージのインストール
npm install lodash
npm install --save-dev typescript @types/lodash
# yarn
yarn add lodash
yarn add -D typescript
# pnpm
pnpm add lodash
pnpm add -D typescript
// package.json
{
"name": "my-project",
"version": "1.0.0",
"dependencies": {
"lodash": "^4.17.21"
},
"devDependencies": {
"typescript": "^5.0.0",
"@types/lodash": "^4.14.0"
}
}
// 使用
import _ from 'lodash';
import { debounce } from 'lodash';
VB.NET(NuGet)
# .NET CLI
dotnet add package Newtonsoft.Json
dotnet add package xunit --version 2.4.1
# パッケージの復元
dotnet restore
# パッケージの更新
dotnet add package Newtonsoft.Json --version 13.0.1
<!-- .vbproj -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
</ItemGroup>
</Project>
' 使用
Imports Newtonsoft.Json
Module Program
Sub Main()
Dim json = JsonConvert.SerializeObject(New With {.Name = "John"})
End Sub
End Module
13.4 モジュールの可視性
PHP
<?php
namespace App;
// すべて public(PHP には internal がない)
class PublicClass {}
// 規約で internal を示す
/** @internal */
class InternalClass {}
TypeScript
// すべてエクスポートされたものは public
export class PublicClass {}
// エクスポートしなければモジュール内のみ
class InternalClass {}
// @internal JSDoc(ドキュメント用)
/** @internal */
export class MarkedInternal {}
VB.NET
' Public(アセンブリ外から参照可能)
Public Class PublicClass
End Class
' Friend(アセンブリ内のみ)
Friend Class InternalClass
End Class
' Private(入れ子クラス)
Public Class Outer
Private Class Inner
End Class
End Class
' Protected Friend
Protected Friend Class ProtectedFriendClass
End Class
13.5 循環参照の回避
PHP
<?php
// 循環参照を避けるためインターフェースを使用
// Contracts/UserRepositoryInterface.php
namespace App\Contracts;
interface UserRepositoryInterface {
public function find(int $id): ?User;
}
// Services/UserService.php
namespace App\Services;
use App\Contracts\UserRepositoryInterface;
class UserService {
public function __construct(
private UserRepositoryInterface $repository
) {}
}
// Repositories/UserRepository.php
namespace App\Repositories;
use App\Contracts\UserRepositoryInterface;
class UserRepository implements UserRepositoryInterface {
// ...
}
TypeScript
// 型のみのインポートで循環を避ける
// types.ts
export interface User {
id: number;
name: string;
}
// userService.ts
import type { User } from './types';
export class UserService {
getUser(): User {
// ...
}
}
// 遅延インポート
export class LazyLoader {
async loadUserService() {
const { UserService } = await import('./userService');
return new UserService();
}
}
VB.NET
' インターフェースを別アセンブリに分離
' Contracts アセンブリ
Namespace Contracts
Public Interface IUserRepository
Function Find(id As Integer) As User
End Interface
End Namespace
' Domain アセンブリ(Contracts を参照)
Namespace Domain
Public Class User
Public Property Id As Integer
End Class
End Namespace
' Infrastructure アセンブリ(Contracts、Domain を参照)
Namespace Infrastructure
Public Class UserRepository
Implements Contracts.IUserRepository
' ...
End Class
End Namespace