Saya mencoba mengembangkan mesin game untuk penggunaan pribadi di JS. Saya ingin mesin saya dapat menggunakan elemen kelas yang terpisah. Salah satu masalah yang saya coba selesaikan adalah metode rantai dari satu kelas (katakanlah kelas matematika yang menghubungkan fungsi) ke fungsi utama saya.

Berikut adalah contoh tampilan yang saya inginkan:

let game = new Engine()
game.operator(5).sum(3).divide(2)

Inilah yang mungkin ada dalam kode saya, meskipun di sinilah saya tidak yakin apa yang harus dilakukan.

class Engine {
   constructor() {
    //Set up engine here
    /* This is where I am unsure how to link the following operator class to this one. 
    * Do I put it here in constructor or ...
    */

   }
   /* ... do I put it here? (Or not in this class at all?)
   *
   * This is what I tried doing as a function
   *
   * operator(input) {
   *    let op = new Operator(input);
   * }
   */
}
class Operator {
    /*The following class is different than the one I am using, but follows similar syntax: 
    * Basic usage: operator(5).sum(3, 4) => Should output 12
    * How the class works is mostly irrelevant, just know it chains methods.
    */
    constructor(input) {
        this.input = input;
        this.answer = this.input;
    }
    sum() {
        let a = arguments[0]
        for(var i = 1; i < arguments.length; i++) {
            a += arguments[i];
        }
        this.answer += a;
        return this;
    }
    divide() {
        let a = arguments[0];

        for(var i = 1; i < arguments.length; i++) {
            a *= arguments[i];
        }
        this.answer /= a;
        return this;
    }

}

Bagaimana saya bisa mendapatkan satu kelas untuk dapat menghubungkan metode dari kelas yang berbeda?

1
Malmadork 30 Oktober 2019, 19:56

2 jawaban

Jawaban Terbaik

Pola untuk rantai adalah membuat instance mempertahankan status rantai, dan menyediakan metode 'nilai' yang mengembalikan status rantai. Untuk menghubungkan antara dua kelas, saya kira saya memiliki metode nilai khusus yang mengembalikan turunan dari kelas lain. (Agar pembaca tetap berorientasi, beri nama sesuatu yang menunjukkan perubahan jenis)...

class ObjectA {
  constructor(string) {
    this.chainValue = string
    this.string = string
  }

  transformA() {
    this.chainValue = this.chainValue.toUpperCase()
    return this
  }

  transformB() {
    this.chainValue = this.chainValue + "bar"
    return this
  }

  // the regular value method
  get value() {
    return this.chainValue
  }

  // like the value method, but named to explicitly return MyNumber
  get numberValue() {
    return new MyNumber(this.value.length)
  }
}

class MyNumber {
  constructor(int) {
    this.chainValue = int
    this.int = int
  }
  
  add(n) {
    this.chainValue += n
    return this
  }
  
  get value() {
    return this.chainValue
  }
}

let a = new ObjectA("foo")
console.log(
  a
  .transformB()   // append "bar"
  .transformA()   // convert to upper case
  .numberValue    // return a number (arbitrarily, the length of the chain state)
  .add(12)        // add 12
  .value          // expect 18
)
2
danh 31 Oktober 2019, 21:05

Anda dapat menggunakan Proxy untuk tujuan itu.

    class Engine {
    operator() {
      // code
      console.log('call operator')
    }
  }
  class Operator {
    sum() {
      // code
      console.log('call sum')
    }

    divide() {
      console.log('call divide')
    }
  }

  class SuperOperator {
    negate() {
      console.log('call negate')
    }
  }

  const operator = new Operator();
  const superOperator = new SuperOperator();
  const engine = new Engine();


  const objectsToChainFrom = [
    engine,
    operator,
    superOperator,
  ];

  // create helper function for proxy
  function wrapper(originalMethod, ctx) {
    return function () {
      originalMethod.apply(ctx, arguments);
      // return proxy;
      return this;
    }
  }

  var proxy1 = new Proxy(objectsToChainFrom, {
    get(target, methodToCall, receiver) {
      const objectWithMethod = target.find(el => el[methodToCall]);
      return wrapper(objectWithMethod[methodToCall], objectWithMethod)
    }
  });

  proxy1
    .sum()
    .operator()
    .divide()
    .negate()
2
Steve 31 Oktober 2019, 08:55