1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

浅いコピー(Shallow Copy)と深いコピー(Deep Copy)の違いを整理する(Dart/ Kotlin 実例付き)

Last updated at Posted at 2025-08-24

はじめに

オブジェクト指向プログラミングでは、「コピー(複製)」 がよく使われます。
特に Prototype パターンcopyWith / copy() のような API を使うときに重要になるのが、

  • 浅いコピー(Shallow Copy)
  • 深いコピー(Deep Copy)

です。
この記事ではその違いを整理し、Flutter(Dart)と Android(Kotlin)の具体例で比較します。


1. 浅いコピー(Shallow Copy)

定義

  • プリミティブ型(int, double, Stringなど) はそのままコピーされる
  • 参照型(List, Map, クラスなど) は「参照だけコピー」される
  • コピー先とコピー元が 同じインスタンスを共有している状態

特徴

  • 高速・軽量
  • だが 独立性がない(片方を変更するともう片方に影響する)

Dart の例

class Engine {
  String type;
  Engine(this.type);
}

class Car {
  String name;
  Engine engine;
  Car(this.name, this.engine);

  // 浅いコピー
  Car shallowCopy() => Car(name, engine);
}

void main() {
  var car1 = Car("Car1", Engine("V8"));
  var car2 = car1.shallowCopy();

  car2.engine.type = "V6";

  print(car1.engine.type); // V6 ← car1 も影響!
}

3. 深いコピー(Deep Copy)

定義

  • プリミティブ型はコピーされる
  • 参照型も 新しいインスタンスを再帰的に生成してコピー
  • コピー先とコピー元は 完全に独立したオブジェクト

特徴

  • 独立性が高い(片方を変更してももう片方に影響しない)
  • だが コピーコストが高い(処理が重い)

Dart の例

class Car {
  String name;
  Engine engine;
  Car(this.name, this.engine);

  // 深いコピー
  Car deepCopy() => Car(name, Engine(engine.type));
}

void main() {
  var car1 = Car("Car1", Engine("V8"));
  var car2 = car1.deepCopy();

  car2.engine.type = "V6";

  print(car1.engine.type); // V8 ← car1 は独立!
}

4. Kotlin の例

浅いコピー(デフォルトの copy()

data class Engine(var type: String)
data class Car(val name: String, val engine: Engine)

fun main() {
    val car1 = Car("Car1", Engine("V8"))
    val car2 = car1.copy() // 浅いコピー

    car2.engine.type = "V6"
    println(car1.engine.type) // V6 ← 影響あり!
}

深いコピー(手動実装)

fun Car.deepCopy(): Car = Car(name, Engine(engine.type))

fun main() {
    val car1 = Car("Car1", Engine("V8"))
    val car2 = car1.deepCopy()

    car2.engine.type = "V6"
    println(car1.engine.type) // V8 ← 独立
}

5. 違いまとめ(早見表)

項目 浅いコピー (Shallow) 深いコピー (Deep)
プリミティブ型 値をコピー 値をコピー
参照型 参照だけコピー(共有) 新しいインスタンスを生成
独立性 低い(影響し合う) 高い(完全に独立)
パフォーマンス 高速・軽量 遅い・重い
典型ユースケース Immutable オブジェクト前提 複雑なネスト構造あり

6. 実務での考え方

Flutter / Dart

  • copyWith を多用(TextStyle, ThemeData など)
  • Immutable 設計なら浅いコピーで十分安全
  • ネストが深い場合は freezedjson_serializabledeep copy 生成 をサポート

Android / Kotlin

  • data class.copy() は浅いコピー(ネスト参照は共有される)
  • 深いコピーが必要なら deepCopy() を実装
  • Immutable モデルを前提にして「浅いコピー+差し替え」で設計するのが一般的

まとめ

  • 浅いコピー:高速・軽量だが参照を共有するため副作用に注意
  • 深いコピー:完全に独立するがコストが高い
  • 実務では Immutable オブジェクト設計と組み合わせ、浅いコピーをベースにすることが多い
  • ネスト構造やミュータブル設計が必要な場合は、深いコピーを導入する
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?