Closed MofuMofu2 closed 1 year ago
set(key: K, value: V)
というメソッドとget(key: K): V | undefined
というメソッドが必要ということだった。
まずは追加してみる。
キャッシュクラスの要件をもう少し整理したいです。setメソッドとコンストラクターはどのように使い分けるといいですか?コードの実装例を出力せずに回答をいただきたいです。
set
メソッドとコンストラクタの使い分けについて説明します。
コンストラクタは、クラスのインスタンスが生成されるときに一度だけ実行される特殊なメソッドです。通常、コンストラクタ内で行われる操作は以下の通りです:
例えば、Cache
クラスでは、内部でキャッシュデータを保持するためのオブジェクトやマップの初期化をコンストラクタ内で行うでしょう。
set
メソッド:set
メソッドは、キャッシュに新しいキーと値のペアを追加したり、既存のキーの値を更新したりするためのものです。キャッシュクラスのインスタンスがすでに生成されている状態で、キーと値のペアを追加するためにset
メソッドを使用します。
コンストラクタ: インスタンスの生成と初期設定に使用します。例えば、内部データ構造の初期化や、キャッシュの容量のような、特定の初期パラメータを設定することが考えられます。
setメソッド: すでに生成されているキャッシュのインスタンスに、新しいキーと値のペアを追加したり、既存のペアの値を更新したりするために使用します。
set
メソッドを使用してデータを追加する方が一般的です。この説明をもとに、キャッシュクラスを設計する際のアプローチを考えることができます。
もっと訳がわからなくなってきた。setでk,vを更新するということ?
提供されたCacheClass
を確認しましたが、実際のキャッシュの動作とは異なります。
以下の問題点があります:
set
メソッドは既存のキーと値を上書きするだけです。これは1つのキーと値のペアしか保存しないためのものですが、これはキャッシュの本来の動作とは異なります。以下のように修正することで、実際のキャッシュの動作を模倣することができます:
Map
を使用します。set
メソッドを使用して、キーと値のペアをキャッシュに追加または更新します。get
メソッドを使用して、指定されたキーに関連付けられている値を取得します。以下は修正後のCacheClass
のサンプルです:
class CacheClass<K, V> {
private cache: Map<K, V>;
constructor() {
this.cache = new Map<K, V>();
}
set(key: K, value: V): void {
this.cache.set(key, value);
}
get(key: K): V | undefined {
return this.cache.get(key);
}
}
このクラスでは、Map
を使用して内部的にキーと値のペアを保存します。set
メソッドを使用してキャッシュにデータを追加または更新し、get
メソッドを使用してデータを取得します。
内部的にはキーと値のペアを保存するためのオブジェクトまたはMapを使用します。
MapはArray.prototype.map以外にもあるのを初めて知った。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Map
2と3は次のAPIを使って実装している。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Map/get https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Map/set
private cache: Map<K, V>; の部分とコンストラクターについてもう少し詳しく解説いただけますか?
もちろん、詳しく解説します。
private cache: Map<K, V>;
この行は、クラスCacheClass
の中でcache
という名前のプライベートメンバ変数を宣言しています。この変数は、キーと値のペアを保持するためのMap
オブジェクトを表しています。
private
: これはアクセス修飾子で、このメンバ変数がクラスの外部からアクセスできないことを示しています。つまり、このcache
変数はCacheClass
クラスのメソッド内でのみ使用できます。
cache
: これはメンバ変数の名前です。
Map<K, V>
: この部分はcache
変数の型を示しています。Map
はES6から導入されたキーと値のペアを保存するためのデータ構造です。<K, V>
の部分はジェネリック型引数で、キーの型がK
、値の型がV
であることを示しています。
constructor() {
this.cache = new Map<K, V>();
}
constructor
: これはクラスのコンストラクタメソッドを定義しています。コンストラクタは、クラスの新しいインスタンスが作成されるときに自動的に実行される特別なメソッドです。
this.cache = new Map<K, V>();
: この行で、cache
メンバ変数に新しいMap
オブジェクトを割り当てています。この時点で、このMap
は空です。新しいキーと値のペアを追加したり、既存のペアを取得したりするために、set
メソッドやget
メソッドを使用します。
この設計により、CacheClass
は内部的にMap
を使用してキーと値のペアを効率的に管理することができます。外部からは、この内部のMap
の詳細を知ることなく、set
やget
メソッドを通じてキャッシュの操作を行うことができます。
うーん、Mapとオブジェクトの違いがよくわからないので質問してみる。
MapとObjectの違いがよくわからないので解説いただけますか?keyとvalueが実行時に型が決まるのでジェネリクスを使うのはわかりましたが、オブジェクト型で指定するときと指定しないときがよくわからないです。
了解しました。まずは、Map
とObject
の違いから説明し、次にTypeScriptでのオブジェクト型の指定に関して説明いたします。
Map
とObject
の違いObject
:
Map
:
size
プロパティで簡単に取得できます。set
, get
, has
, delete
などの便利なメソッドがあります。TypeScriptでは、オブジェクトの型を指定する方法が複数あります。
指定しない場合: TypeScriptは型推論を用いてオブジェクトの型を自動的に推論します。
let obj = { name: "Alice", age: 25 };
// objの型は { name: string; age: number; } と推論される
明示的に型を指定する場合: オブジェクトの型を明示的に指定できます。
let obj: { name: string; age: number; } = { name: "Alice", age: 25 };
インターフェースや型エイリアスを使用する場合: より複雑なオブジェクトの型を定義する場合、インターフェースや型エイリアスを利用することが推奨されます。
interface Person {
name: string;
age: number;
}
let obj: Person = { name: "Alice", age: 25 };
このように、TypeScriptではオブジェクトの型をどのように指定するか、または推論を利用するかに応じて柔軟に対応できます。どの方法を選ぶかは、ケースやコードの構造、チームのコーディングガイドラインなどに依存します。
JavaScriptだと全てがobjectで、ここから派生している。なので組み込み = プロトタイプがある
https://jsprimer.net/basic/prototype-object/ https://developer.mozilla.org/ja/docs/Learn/JavaScript/Objects/Object_prototypes
シンボルはユニークな識別子(かぶっちゃだめ)のこと。普段は用途が思いつかなさそう。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol https://ja.javascript.info/symbol
key-valueのペアがくるが、何が出てくるかは実行しないとわからないみたいなときはジェネリクスを使う。 基本はinterfaceを指定することになりそう。
キーと値のペアを保存するためのジェネリックなキャッシュクラスCacheを作成してください。このクラスは、set(key: K, value: V)とget(key: K): V | undefinedという2つのメソッドを持つべきです。
class Cache<K, V> { // ここに実装 }