我实际上是想找到一种方法在AS3中通过引用,但似乎adobe和许多人对通过引用传递的理解与我在大学里所教授的不同。我被教导java是通过值传递的,C ++允许通过引用传递。
我并没有试图争论通过价值和参考传递的是什么。我只想解释为什么我在问题中使用pass by object ...
回到这个问题,我想做点什么:
public function swapCard(cardA:Cards, cardB:Cards) {
var temp:Cards = cardA;
cardA = cardB;
cardB = temp;
}
...
swapCard(c1, c2);
编辑:添加两个关于我如何使用swapCard函数的例子
1)在播放器1和播放器2之间交换卡片的过程
swapCard(player1.hand[s], player2.hand[t]);
2)在玩家1的手和牌组之间交换牌的过程中
swapCard(player1.hand[s], player1.deck[rand]);
在C ++中,我们只需要在参数之前添加符号以使其工作(我们称之为通过引用传递)。但在AS3中,cardA和cardB只是指向形式参数的指针。在函数中,更改指针对形式参数没有任何作用:(
我一直在寻找几个小时,但在不知道卡的所有属性的情况下我找不到办法。
如果我必须逐个更改卡的属性,那么我可能应该将swapCard更改为类卡中的静态功能吗? (因为我不想把所有东西都暴露给另一个班级)我不确定这是不是一个好习惯。这就像在类Cars中添加swap_cars函数一样。如果我让这件事发生,接下来会发生什么?洗车,借车,租车...我真的想保持卡类清洁,只保留卡的详细信息。有没有可能在AS3中正确执行此操作的方法?
答案 0 :(得分:5)
在AS3中无法实现您尝试实施的swap
功能。输入参数是对输入对象的引用,但引用本身是按值传递的。这意味着您可以在函数内部更改cardA
和cardB
,但这些更改在函数外部将不可见。
修改:在您使用示例用法编辑问题后,我添加了此部分。
您似乎正在尝试在两个不同的数组中交换两个对象,每个数组在给定的数组位置 - 您可以在AS3中为此创建一个函数,但不是您尝试的方式。
一种可能的实现方式是传递数组本身以及您尝试交换的位置;像这样的东西:
// Assumes arrays and indices are correct.
public function SwapCards(playerHand:Array, playerCardIndex:int,
playerDeck:Array, playerDeckIndex:int):void
{
var tempCard:Card = playerHand[playerHandIndex];
playerHand[playerHandIndex] = playerDeck[playerDeckIndex];
playerDeck[playerDeckIndex] = tempCard;
}
请注意,您仍然交换引用,并且数组本身仍然通过引用传递(并且数组引用按值传递 - 如果您愿意,可以将数组更改为此函数中的新数组,但是您不会这样做。看到外面的新阵列)。但是,因为数组参数引用函数内部和外部的相同数组,所以可以更改数组的内容(或其他数组属性)以及这些更改将在外面可见。
此解决方案比克隆卡更快,因为这涉及为新的Card
实例分配内存(这是昂贵的),并且临时实例也必须由垃圾收集器释放(这也很昂贵)
您在评论中提到您将卡片传递到较低级别的代码 - 如果您没有对阵列的后向引用(以及卡片的位置),您将无法轻松交换卡 - 在AS3中,所有输入参数都是副本(基本类型的值的副本或复杂对象的引用的副本 - 函数中输入参数的更改在外部不可见。)
答案 1 :(得分:0)
编辑:如aaron所指出的,将函数从clone重命名为copyFrom。似乎克隆应该用作objA = objB.clone()
此时,我在Cards类中添加了copyFrom()函数,以便
var temp:Cards = new Cards(...);
var a:Cards = new Cards(...);
...
temp.copyFrom(a);
...
temp将复制来自。
的所有内容public function swapCard(cardA:Cards, cardB:Cards) {
var temp:Cards = new Cards();
temp.copyFrom(cardA);
cardA.copyFrom(cardB);
cardB.copyFrom(temp);
}
我会等一个星期左右看看是否还有其他选择
答案 2 :(得分:0)
你已经有了一些很好的答案,但根据我来回的评论,这是我的建议(我使用"左"和"右"命名,因为它有助于我想象,但它并不重要):
function swapCard(leftCards:Array, leftCard:Card, rightCards:Array, rightCard:Card):void {
var leftIndex:int = leftCards.indexOf(leftCard);
var rightIndex:int = rightCards.indexOf(rightCard);
leftCards[leftIndex] = rightCard;
rightCards[rightIndex] = leftCard;
}
现在你可以在你发布的两个例子中交换卡片:
swapCard(player1.hand, player1.hand[s], player2.hand, player2.hand[t]);
swapCard(player1.hand, player1.hand[s], player1.deck, player1.deck[rand]);
但是,请注意,虽然这会在数组中交换卡,但它不会直接引用这些数组中的卡。换句话说:
var a:Card = player1.hand[0];
var b:Card = player2.hand[0];
swapCard(player1.hand, a, player2.hand, b);
// does not change the references a and b, they still refer to the same card
a == player2.hand[0];
a != player1.hand[0];
b == player1.hand[0];
b != player2.hand[0];
通常情况下,通过调度"更改"来处理此类事情。事件,以便任何关心玩家手部阵列状态的代码都知道重新评估手的状态。
答案 3 :(得分:-1)
这里发生了很深的误会。问题是关于对象引用,但PO并没有尝试交换任何Object引用。
问题来自于PO不理解变量和对象之间的差异。他试图交换变量/对象引用,当然这不是动态可能的。他想要一个函数使变量持有对象A的引用,将其对象引用与另一个变量交换。由于对象可以传递而不是变量(因为它们只是持有者(而不是指针)),如果不直接使用给定变量,则无法执行任务。
要恢复:
变量不是对象! 变量包含对象的引用。 变量不能在函数中传递或在函数中引用,因为它们不是对象。