对象的字段实例是不是可以调用对象本身? (JavaScript)

Posted

技术标签:

【中文标题】对象的字段实例是不是可以调用对象本身? (JavaScript)【英文标题】:Is it possible for a field instance of an object to call upon the object itself? (JavaScript)对象的字段实例是否可以调用对象本身? (JavaScript) 【发布时间】:2021-12-19 21:11:57 【问题描述】:

TL;DR

如果一个对象 X 有一个对象 Y 作为它的字段实例,有没有办法让 Y 调用或检索 X而不将 X 指定为 Y 的字段实例


我正在编写一个 javascript 程序来实现 Farkle,这是一个基于骰子的游戏。为了运行 Farkle 游戏,我实例化了 FarkleGame 类的一个实例。这涉及 FarklePlayer 类的两个实例化和 FarkleDie 类的一个实例化。两个 FarklePlayer 实例(代表玩 Farkle 的两个人)和一个 FarkleDie 实例(代表 Farkle 中使用的一个骰子)被分配为 中的字段实例FarkleGame 类并在 FarkleGame 构造函数中初始化。但是,两个 FarklePlayer 实例需要能够访问存在于 FarkleGame 类定义中但在它们自己的 FarklePlayer 类定义之外的数据。 p>

例如: 一个人必须在 Farkle 中掷骰子,并且可能会根据掷骰的值获得分数。我希望 FarklePlayer 实例通过访问更高级别 FarkleGame 实例的 die 字段属性以及 score_die() 来启动掷骰子 方法。

这是一个示例控制流程:

    FarkleGame 实例询问 FarklePlayer 实例她是否想通过她的回合或滚动

    FarklePlayer 实例选择滚动,并调用她的类方法roll()

    但 FarklePlayer 类方法 roll() 实际上是检索属于更高级别 FarkleGame 实例的 FarkleDie 实例,并告诉 FarkleDie 实例调用 rolled(),如以及检索更高级别的 FarkleGame 实例并告诉它调用 score_die()

class FarkleGame 
  player_one;
  player_two;
  die;

  constructor(name_of_player_one, name_of_player_two) 
    this.player_one = new FarklePlayer(name_of_player_one);
    this.player_two = new FarklePlayer(name_of_player_two);
    this.die = new FarkleDie();
  



  get_player_one() 
    return this.player_one;
  
  
  get_player_two() 
    return this.player_two;
  

  get_die() 
    return this.die;
  

  score_die() 
    let die_value = this.get_die().get_value();
    let score = ((die_value * die_value) * 10) - 1);  






class FarklePlayer  
  name;
    constructor(name_of_player) 
        this.name = name_of_player;


     roll() 
           // FarklePlayer instance wants to roll and needs to access the 
           // die field attribute and score_die() method of the 
           // higher-level FarkleGame instance of which it is a part of.

      higher_level_FarkleGame_instance.get_die().rolled();
      higher_level_FarkleGame_instance.score_die();





class FarkleDie 

  value;
  
  constructor() 
    this.value = null;
  

  rolled() 
    let value_after_rolled = (Math.floor(Math.random() * 6) + 1);
    this.value = value_after_rolled;
  



请务必注意,我不想将 FarkleDie 实例作为参数传递给 FarklePlayer roll() 方法。我希望 FarklePlayer roll() 方法访问更高级别的数据(即 FarkleGame 实例的字段实例),甚至指示其更高级别的实例做某事(通过调用方法定义FarkleGame 类)。

低级实例如何调用它们所属的高级实例的字段和方法?

提前谢谢你。

【问题讨论】:

既然玩家在游戏的上下文中行动或必须行动,为什么 OP 不在每个玩家的实例化时将游戏(实例)传递给玩家的构造函数? @PeterSeliger 您好 Seliger 先生,感谢您的评论和回复。我理解你的解决方案,这很有意义。我希望通过 FarklePlayer 实例(后者是前者的字段实例)访问 FarkleGame 实例。尽管您的解决方案确实有效,但它不允许独立的类实例化,也不遵守我最初设计的较低/较高级别的指定。你知道对象的字段实例是否可以调用对象本身吗?用类似于“超级”调用的东西说? (我知道“超级”指的是超类。) 在我的回答下方查看我的详细评论。原始帖子的编辑/更改主题的简短答案... “对象的字段实例是否可以调用对象本身?” ...是... 是的,这是可能的。一个人总是必须明确地向字段本身提供这个上下文(非常对象)...... 1)在调用时(如果该字段是一种可以使用call/apply的方法)...... 2)或者通过实例化/创建时间(如果该字段是构造/创建的对象,则将非常父对象作为对构造函数/工厂的引用传递)。 【参考方案1】:

OP ...

重要的是要注意我不想将FarkleDie 实例作为参数传递给某些FarklePlayerroll 方法。

我希望FarklePlayerroll 方法访问更高级别的数据(即FarkleGame 实例的字段属性)

从上面的评论...

“既然玩家在游戏的上下文中行动或必须行动,为什么 OP 在每个玩家的实例化时不将游戏(实例)传递给玩家的构造函数?”

那为什么不做显而易见的事呢。一个游戏实例包含所有需要的引用。因此,player 确实通过其 game 引用访问了 die

class FarkleGame 
  constructor(firstPlayerName, secondPlayerName) 
    this.playerOne = new FarklePlayer(firstPlayerName, this);
    this.playerTwo = new FarklePlayer(secondPlayerName, this);
    this.die = new FarkleDie();
  /*
  Why prototypal getters, since all
  the properties are public anyhow?

  getPlayerOne() 
    return this.playerOne;
  
  getPlayerTwo() 
    return this.playerTwo;
  
  getDie() 
    return this.die;
  */


class FarklePlayer  
  constructor(name, game) 
    this.name = name;
    this.game = game;
  
  roll() 
    this.game.die.rolled();
  


class FarkleDie 
  constructor() 
    this.value = null;
  
  rolled() 
    this.value = (Math.floor(Math.random() * 6) + 1);
  


const game = new FarkleGame('Jill', 'Jack');

console.log(
  'game.die.value:',
  game.die.value
);

console.log(
  '... game.playerOne.roll() ...',
);
game.playerOne.roll();

console.log(
  'game.die.value:',
  game.die.value
);

console.log(
  '... game.playerTwo.roll() ...',
);
game.playerTwo.roll();

console.log(
  'game.die.value:',
  game.die.value
);
.as-console-wrapper  min-height: 100%!important; top: 0; 

【讨论】:

您好 Seliger 先生,感谢您的评论和回复。我理解你的解决方案,这很有意义。我希望通过 FarklePlayer 实例(后者是前者的字段实例)访问 FarkleGame 实例。尽管您的解决方案确实有效,但它不允许独立的类实例化,也不遵守我最初设计的较低/较高级别的指定。你知道对象的字段实例是否可以调用对象本身吗?用类似于“超级”调用的东西说? (我知道“超级”指的是超类。) @Rar ... 最后你需要有互连的实例。没有其他办法。您自己的设计使两个players 和die 的一部分game。因此,如果 player 将变为 roll,则需要知道 die。当然,这不能仅通过最通用的播放器抽象的最基本实现来实现(您使用 “它不允许独立的类实例化” 解决的问题)。是的,确实需要一个 GamePlayer 抽象,它根据定义知道它正在参与的游戏。 我无法为您的答案投票,因为我还没有 15 名声望。也许如果您对我的问题表示支持,我将获得必要的声誉来支持您的回答?

以上是关于对象的字段实例是不是可以调用对象本身? (JavaScript)的主要内容,如果未能解决你的问题,请参考以下文章

java 反射

java利用构建器来创建实例而不是构造器

java编程学习笔记

python3类方法,实例方法和静态方法

java基础(杂记)

VS提示“非静态的字段,方法或属性要求对象引用”