Flash ActionScript2.0 実践講座3:Flash OOP詳細

本日の予定

先週の授業に引き続き、Flashを用いてオブジェクト指向プログラミング(OOP)を行う方法について学びます。今回はColin Moock氏によるレクチャー資料を参照しながら、OOPについての概念の大枠を整理し、その後、サンプルプログラムを作成しながら具体的にOOPについて実践的に学んでいきます。

本日のスライド

サンプルファイル

目次

OOP (Object Oriented Programiing)の用語のまとめ

このスライドについて

オブジェクト指向プログラミング(OOP)とは

クラス(classes)とは

クラスの中身

高レベルの集合体

なんでOOPにするの?

クラスからオブジェクト(objects)が生まれる

OOP、3つのステップ

「たまごっち」を作ってみる

コードの実例でさらにOOPについての理解を深めていく

クラスファイル

クラスの宣言

メソッド:クラスのふるまい

消化:digest()メソッド

論理が先、表示は後で

publicとprivate

オブジェクトの生成

オブジェクトの保持

.flaファイルからクラスにアクセスする

クラスにアクセスする別の方法

餌をやる:the feed() メソッド

オブジェクトのメソッドを呼び出す

下記のコードを復習

まちがったメソッドを呼び出すとどうなるか?

データタイプと正しいメソッド

たまごっちは歌えない

状態の管理

Tamagotchiのプロパティ

正しい型のデータの保存storing the right type of data

現状のTamagotchiクラス

class Tamagotchi {
  private var currentCalories:Number;
  private var name:String;
    
  private function digest () {
    trace("たまごっち消化中...");
  }

  public function feed () {
    trace("あなたは、たまごっちに餌をやりました...");
  }
  
}

privateプロパティ

わたしのプロパティは、あなたにはわからない

アクセサメソッド(accessor methods)

プロパティ設定アクセサ

設定アクセサの使いかた

プロパティー取得アクセサ

カプセル化

カプセル化の利点(設定フィルタリング)

カプセル化の利点(取得フィルタリング)

コンストラクタ関数

Tamacotchiのコストラクタ

オブジェクトの初期化

クラスプロパティシンタックス

マジックバリュー

マジックバリューは良くない

マジックバリューをクラスプロパティとして保存する

初期値をクラスプロパティとして保存する

現在のTamagotchiクラスの状態

class Tamagotchi {
    private var currentCalories:Number;
    private var name:String;
    private static var MAX_NAME_LENGTH:Number = 20;
    private static var DEFAULT_NAME:String = "名無しさん";
    public function Tamagotchi (petName) {
	setName(petName);
    }
    private function digest () {
	trace("たまごっちは消化中...");
    }
    public function feed (foodItem) {
	trace("あなたはたまごっちに餌をあげました.");
    }
    public function setName (newName) {
	if (newName.length > Tamagotchi.MAX_NAME_LENGTH) {
	    trace("警告:名前が長すぎます");
	    newName = newName.substr(0, Tamagotchi.MAX_NAME_LENGTH);
	} else if (newName == "") {
	    trace("警告:名前が短すぎます.");
	    return;
	}
	name = newName;
    }
    public function getName () {
	if (name == null) {
	    return Tamagotchi.DEFAULT_NAME;
	} else {
	    return name;
	}
    }
}

Tamagotchiの生命

最大カロリー

カロリー消費レート

生か死か?

死ぬまで消化し続ける、死んだら消化が停止する

Tamagotchiの誕生

Tamagotchi の死

die()メソッド全体

private function die () {
    clearInterval(digestIntervalID);
    isAlive = false;
    Key.removeListener(this);
    trace(getName() + " has died.");
}

カロリーの消費

現状のTamagotchiクラス

class Tamagotchi {
    private var currentCalories:Number;
    private var name:String;
    private var isAlive:Boolean;
    private var digestIntervalID:Number;
    private static var MAX_NAME_LENGTH:Number= 20;
    private static var DEFAULT_NAME:String= "Unnamed Pet";
    private static var MAX_CALORIES:Number= 2000;
    private static var CALORIES_PER_SECOND:Number = 100;
    public function Tamagotchi (petName) {
	setName(petName);
	currentCalories = Tamagotchi.MAX_CALORIES;
	isAlive = true;
	digestIntervalID = setInterval(this, "digest", 1000);
    }
    private function digest () {
	trace("The Tamagotchi is digesting...");
	currentCalories -= Tamagotchi.CALORIES_PER_SECOND;
	if (currentCalories <= 0) {
	    die();
	} else {
	    displayHealthStatus();
	}
    }
    public function feed (foodItem) {
	trace("You fed the Tamagotchi.");
    }
    private function displayHealthStatus () {
	var caloriePercentage:Number 
	    = Math.floor((currentCalories/Tamagotchi.MAX_CALORIES)*100);
	trace(getName() + " has " + currentCalories + " calories"
	      + " (" + caloriePercentage + "% of its food) remaining.");
    }
    private function die () {
	clearInterval(digestIntervalID);
	isAlive = false;
	Key.removeListener(this);
	trace(getName() + " has died.");
    }
    public function setName (newName) {
	if (newName.length > Tamagotchi.MAX_NAME_LENGTH) {
	    trace("Warning: specified name is too long.");
	    newName = newName.substr(0, Tamagotchi.MAX_NAME_LENGTH);
	} else if (newName == "") {
	    trace("Warning: specified name is too short.");
	    return;
	}
	name = newName;
    }
    public function getName () {
	if (name == null) {
	    return Tamagotchi.DEFAULT_NAME;
	} else {
	    return name;
	}
    }
}

Tamagotchiの食べ物:寿司とリンゴ

類似点を分解する

継承

Foodクラスのソース

class Food {
    private var calories;
    private var name;
    public function Food (initialCalories:Number) {
	setCalories(initialCalories);
    }
    public function getCalories () {
	return calories;
    }
    public function setCalories (newCalories) {
	calories = newCalories;
    }
    public function getName () {
	return name;
    }
    public function setName (newName) {
	name = newName;
    }  
}

Sushiクラス(subclass)

superclassのコンストラクタを呼び出す

Appleクラス

メソッドは型を返す

なんでメソッドの宣言は型を返すの?

メソッドの引数の型

Tamagotchiになにを食べさせているのか?

ここまでのまとめ

class Tamagotchi {
    private var currentCalories:Number;
    private var name:String;
    private var isAlive:Boolean;
    private var digestIntervalID:Number;
  
    private static var MAX_NAME_LENGTH:Number = 20;
    private static var DEFAULT_NAME:String = "Unnamed Pet";
    private static var MAX_CALORIES:Number = 2000;
    private static var CALORIES_PER_SECOND:Number = 100;

    public function Tamagotchi (petName:String) {
	setName(petName);
	currentCalories = Tamagotchi.MAX_CALORIES;
	isAlive = true;
	digestIntervalID = setInterval(this, "digest", 1000);
    }
    private function digest ():Void {
	trace("The Tamagotchi is digesting...");

	currentCalories -= Tamagotchi.CALORIES_PER_SECOND;
	if (currentCalories <= 0) {
	    die();
	} else {
	    displayHealthStatus();
	}
    }
  
    public function feed (foodItem:Food):Void {
	if (isAlive == false) {
	    trace(getName() + " is dead. You can't feed it.");
	    return;
	}
    
	trace(getName() + " ate the " + foodItem.getName() 
	      + " (" + foodItem.getCalories() + " calories).");
    
	if (foodItem.getCalories() + currentCalories 
	    > Tamagotchi.MAX_CALORIES) {
	    currentCalories = Tamagotchi.MAX_CALORIES;
	} else {
	    currentCalories += foodItem.getCalories();
	}  
    }
    private function displayHealthStatus ():Void {
	var caloriePercentage:Number 
	    = Math.floor((currentCalories/Tamagotchi.MAX_CALORIES)*100);
	trace(getName() + " has " + currentCalories + " calories"
	      + " (" + caloriePercentage + "% of its food) remaining.");
    }

    private function die ():Void {
	clearInterval(digestIntervalID);
	isAlive = false;
	Key.removeListener(this);

	trace(getName() + " has died.");
    }
  
    public function setName (newName:String):Void {
	if (newName.length > Tamagotchi.MAX_NAME_LENGTH) {
	    trace("Warning: specified name is too long.");
	    newName = newName.substr(0, Tamagotchi.MAX_NAME_LENGTH);
	} else if (newName == "") {
	    trace("Warning: specified name is too short.");
	    return;
	}
	name = newName;
    }
    public function getName ():String {
	if (name == null) {
	    return Tamagotchi.DEFAULT_NAME;
	} else {
	    return name;
	}
    }
}
class Food {
    private var calories:Number;
    private var name:String;
    public function Food (initialCalories:Number) {
	setCalories(initialCalories);
    }
    public function getCalories ():Number {
	return calories;
    }
    public function setCalories (newCalories:Number):Void {
	calories = newCalories;
    }
    public function getName ():String {
	return name;
    }
    public function setName (newName:String):Void {
	name = newName;
    }  
}
class Sushi extends Food {
    private static var DEFAULT_CALORIES:Number = 500;
    public function Sushi () {
	super(Sushi.DEFAULT_CALORIES);
	setName("Sushi");
    }
}
class Apple extends Food {
    private static var DEFAULT_CALORIES:Number = 100;
    public function Apple () {
	super(Apple.DEFAULT_CALORIES);
	setName("Apple");
    }
}

ユーザからの入力を処理する

keyboard入力に反応する

キーボードのイベントを登録する

画像表示を追加する

Tamagotchiシンボル

TamagotchiSymbolの中身

ムービクリップを扱うプロパティ

コンストラクタ関数の更新

TamagotchiSymbolのインスタンスをつくる

Tamagotchiの名前を表示する

たまごっちの死を表示する

完成コード

class Tamagotchi {
    private var currentCalories:Number;
    private var name:String;
    private var isAlive:Boolean;
    private var digestIntervalID:Number;
    private var clip:MovieClip;
    private static var MAX_NAME_LENGTH:Number  = 20;
    private static var DEFAULT_NAME:String = "Unnamed Pet";
    private static var MAX_CALORIES:Number = 2000;
    private static var CALORIES_PER_SECOND:Number = 100;
    private static var SYMBOL_ID:String  = "TamagotchiSymbol";
    public function Tamagotchi 
	(petName:String, target:MovieClip, depth:Number, x:Number, y:Number) {
	clip = target.attachMovie(Tamagotchi.SYMBOL_ID, "tamagotchi" + depth, depth);
	clip._x = x;
	clip._y = y;
	setName(petName);
	currentCalories = Tamagotchi.MAX_CALORIES;
	isAlive = true;
	digestIntervalID = setInterval(this, "digest", 1000);
	Key.addListener(this);
    }
    public function feed (foodItem:Food):Void {
	if (isAlive == false) {
	    trace(getName() + " is dead. You can't feed it.");
	    return;
	}
	trace(getName() + " ate the " + foodItem.getName() 
	      + " (" + foodItem.getCalories() + " calories).");
	if (foodItem.getCalories() + currentCalories > Tamagotchi.MAX_CALORIES) {
	    currentCalories = Tamagotchi.MAX_CALORIES;
	} else {
	    currentCalories += foodItem.getCalories();
	}  
    }
    public function setName (newName:String):Void {
	if (newName.length > Tamagotchi.MAX_NAME_LENGTH) {
	    trace("Warning: specified name is too long.");
	    newName = newName.substr(0, Tamagotchi.MAX_NAME_LENGTH);
	} else if (newName == "") {
	    trace("Warning: specified name is too short.");
	    return;
	}
	name = newName;
	clip.name_txt.text = name;
    }
    public function getName ():String {
	if (name == null) {
	    return Tamagotchi.DEFAULT_NAME;
	} else {
	    return name;
	}
    }
    private function die ():Void {
	clearInterval(digestIntervalID);
	isAlive = false;
	Key.removeListener(this);
	trace(getName() + " has died.");    
	clip.gotoAndStop("dead");
    }
    private function displayHealthStatus ():Void {
	var caloriePercentage:Number 
	    = Math.floor((currentCalories/Tamagotchi.MAX_CALORIES)*100);
	trace(getName() + " has " + currentCalories + " calories"
	      + " (" + caloriePercentage + "% of its food) remaining.");
	if (caloriePercentage < 20) {
	    clip.hungerIcon.gotoAndStop("starving");
	} else if (caloriePercentage < 50) {
	    clip.hungerIcon.gotoAndStop("hungry");
	} else {
	    clip.hungerIcon.gotoAndStop("full");
	}
    }
    private function digest ():Void {
	trace("The Tamagotchi is digesting...");
	currentCalories -= Tamagotchi.CALORIES_PER_SECOND;
	if (currentCalories <= 0) {
	    die();
	} else {
	    displayHealthStatus();
	}
    }
    private function onKeyDown ():Void {
	if (Key.getCode() == 65) {
	    feed(new Apple());
	} else if (Key.getCode() == 83) {
	    feed(new Sushi());
	}
    }
}

Comments

コメントはありません

Add Comment

このアイテムは閉鎖されました。このアイテムへのコメントの追加、投票はできません。

トップページに戻る