質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

824閲覧

javascript(node.js)のクラス設計:playerにroleを持たせたい

udoP_

総合スコア6

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

1グッド

0クリップ

投稿2020/02/25 03:28

編集2020/02/25 03:33

実現したいこと

node.jsの初心者です。
オンラインゲームを作っており、その中で参加者(player)に役割(role)を持たせたいです。
参加者それぞれに好きな役割を選ばせる形です。

これの実現として、次のような形を考えています(実際のコードではなく、例です)

class Player{ consutructor(name){ this.name = name this.role = null } takeRole(role){ //?? } solo(){ if(this.role.canSolo){ console.log("俺の歌を聞け!") } } } class Role{ constructor(type){ this.type = type this.vocal = 300 this.dance = 300 this.visual = 300 this.canSolo = false } totalAppeal(){ return this.vocal + this.dance + this.visual } } class Vocalist extends Role{ constructor(){ super("vocalist") this.vocal = 700 this.canSolo = true } } //Roleは他にも複数存在

roleはほぼ構造体です。

疑問

問題はtakeRoleの部分です。
playerに与えるroleが決まっていれば

//player内 takerole(role){ this.role = role } var uduki = new Player("uduki") uduki.takeRole(new Vocalist())

などとすれば良いように思うのですが、
udukiから希望するroletypeを受け取ってroleを設定しようとすると、

uduki.takeRole("Vocalist")

のような形でコールせざるを得ないと考えています。
この時takeRole内部でどう処理をすればいいのかがわかりません。

考えたこと

・roleManagerのようなオブジェクト、あるいはクラスを作る
すなわち、

var roleManager = { "Vocalist": Vocalist, "Dancer": Dancer, "Performer": Performer } //player内 takeRole(roleName){ this.role = new roleManager[roleName]() } var uduki = new Player("uduki") uduki.taleRole("Vocalist")

のような形にすればやりたいことは達成できますが、
この形だと、roleの種類だけroleManagerの行数を増やさなくてはならず、あまりスマートに思えません。
(roleは将来的に増やしていくことを考えています。)

あるいは、

class Role{ constructor(type){ this.type = type this.vocal = 300 this.dance = 300 this.visual = 300 this.canSolo = false switch(type){ case "Vocalist": this.canSolo = true this.vocal = 700 break case "Dancer": //以下延々と処理 } } } uduki.takeRole(new Role(roleName))

のような方法も考えましたが、これはもっと筋が悪い気がします。
evalは…さすがに論外ですよね。

質問

①この方針で行く場合、takeRoleの実装はどのような方法がスマート、あるいはスタンダードですか?

②そもそも、現状の設計は理にかなっているものですか?
ほぼメソッドを持たないRoleクラスに違和感を感じていて、その情報をplayerに持たせれば十分なような気もしています。
その場合は、どのような形にすべきですか?

miyabi_pudding👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

コードを書くと、こちらが開発してしまうことになりそうなので、考え方、構成のヒントだけ回答できればと思います。
①というより、②の部分での話になるかと思います。

  • Playerクラスをオーバーライドしたクラスを用意する

各ロールを、Playerクラスをオーバーライドしたクラスにて実装をまずすべきと思います。
もしくは、Playerクラスに、roleメンバを用意し、Roleクラスを別で用意し、各ロールを、Roleクラスをオーバーライドしたクラスとし、Playerの初期化時に、指定されたロールのクラスのインスタンスを、roleメンバに代入(初期化)するとかですね。
これで一元管理しつつ、各ロール別の特性の定義もしやすくなるでしょう。

と、既にそのような実装をしていたようなので、下記の実装の仕方で、大方解決できるかと。

  • 上記を踏まえ列挙型の定義をする

多くの静的型付け言語には、列挙型という、便利なデータ型がありますので、
それを使うと、より効率的な開発ができるかと思います。
(詳しくはお調べを)
ただし、JavaScriptは動的型付けなので、列挙型は存在しませんので、自身で実装するか、TypeScriptの使用をお勧めします。
Node.jsでの開発なら、容易に導入できるかと思いますよ。
むしろ、列挙型を使わなくても、TypeScriptの方が、ゲーム開発ならばかなり優位になるかと思います。

  • constructor.nameないし、instanceofキーワードを使い、クラスを特定

JavaScriptにおいて、そのインスタンスが、どのクラスで初期化されたかどうかは、上記のプロパティ、キーワードを使えば確かめることができるので、その情報を使い、処理を分けるという方法もあります。

また、下記に、JavaScriptにての、列挙型の実装例を記載いたしますので、
参考にしてください。

javascript

1const EnumCaseStruct = (() => { 2 const key = Symbol(); 3 4 return class EnumCaseStruct { 5 constructor(val) { 6 this[key] = val; 7 } 8 // Swiftを参考に、rawValueで、値を取得できるようにしている 9 get rawValue() { 10 return this[key]; 11 } 12 }; 13})(); 14 15class Enum { 16 constructor(...cases) { 17 if (!cases.every(v => { 18 switch (typeof v) { 19 case 'object': 20 // オブジェクトの場合、各キー値にて、上のクラスのインスタンスとして定義 21 Object.keys(v).forEach(ve => { 22 Object.defineProperty(this, ve, {value: new EnumCaseStruct(v[ve])}); 23 }); 24 return true; 25 case 'string': 26 // 文字列型なら、そのまま初期化する 27 Object.defineProperty(this, v, {value: new EnumCaseStruct(v)}); 28 return true; 29 defalult: 30 // オブジェクトか、文字列型以外は受け付けないようにする 31 return false; 32 } 33 })) { 34 // オブジェクトか文字列以外は、エラーをスローする 35 throw new Error('Type error!'); 36 } 37 } 38} 39 40// 使い方 41const fruits = new Enum( 42 {apple: 25}, 43 {melon: 125} 44); 45 46const apple01 = fruits.apple; 47const apple02 = fruits.apple; 48console.log(apple01 == apple02); // true 49 50// 可変長引数のため、下記のようにも定義可能 51const fruits02 = new Enum( 52 { 53 apple: 25, 54 melon: 125 55 }, 56 'pine' 57); 58// 各列挙型は各値が一意となるため、比較時は偽となる。 59console.log(fruits.apple == fruits02.apple); // false 60// Swiftを参考に、rawValueにて、設定した値を返す 61console.log(fruits.apple.rawValue); // 25 62// 文字列をそのまま入れた場合は、rawValueはその文字列を返す 63console.log(fruits.pine.rawValue); // pine

一例なので、もっといい、もっと列挙型っぽい定義はできるかと思います。

大雑把な概念などの話で恐縮ですが、以上になります。
開発のヒントになれば幸いです。

投稿2020/02/25 04:16

編集2020/02/26 04:14
miyabi_takatsuk

総合スコア9528

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

udoP_

2020/02/25 08:30

素早い回答ありがとうございます。 列挙型については知りませんでした。調べてみるとまさに求めていたものでした。 ですがjsにはないとのことで、現状のプログラムに組み込もうとすると、 結局質問に書いたような辞書的なものを作ることになるのかな、と考えています。 TypeScriptを採用すればいいのかな、とも思うのですが、 型がかっちりしている言語に苦手意識があり(慣れればそちらのほうが楽なのでしょうが) いきなり採用はハードルが高いので、学ぶことから始めようと思います。
miyabi_takatsuk

2020/02/25 09:53

確かに、JavaScriptとか動的型付け慣れしてると、静的型付けやるのはハードル高いですよね 汗 Set型(配列のようなものだが、違うデータ型)、Symbol型値(そのスレッド内では完全に一意なデータ)を上手く使うと、列挙型みたいなものを実装できるかと思いますよー
miyabi_takatsuk

2020/02/26 04:15

JavaScriptにての列挙型っぽいものを回答に追記してみたので、 ご参考いただければ幸いです。
udoP_

2020/02/26 06:40

ご丁寧にありがとうございました。頂いたコードも読んで、理解を深めようと思います。 BAとさせていただきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問