【问题标题】:Invoking methods on objects in java在java中调用对象的方法
【发布时间】:2010-04-15 10:50:51
【问题描述】:

这是 Dice 类的相关部分:

import java.util.*;
class Dice 
{ 
    String name ; 
    int x ; 
    int[] sum ; 

...

public Dice (String name) 
    { 
        this.name = name ; 
        this.x = 0 ; 
        this.sum = new int[7] ; 
    }

...

public void roll () 
    {
        this.x = randNum(1, this.sum.length) ; 
        this.sum[x] ++ ;
    }

我在一个名为 Risk 的单独类中调用此方法

class Risk 
{

这是方法的第一行:

public static void IdiceRoll (Dice o)

所以这个方法需要一个已经存在的骰子作为参数,所以不需要在里面创建一个新的骰子。

这是我尝试在o 上调用roll 的方式:

o.Dice.roll () ; 

【问题讨论】:

  • 请注意,(免费)Sun 文档包括几个教程,这些教程对于学习此类内容非常有用。 java.sun.com/docs/books/tutorial
  • 这篇文章有问题吗?
  • @luis.espinal 曾经有,显然在编辑中丢失了

标签: java


【解决方案1】:

在您的其他类中,在某些方法中,您需要获取您尝试使用的类的实例。如果您在另一个包中,则需要导入语句。

那么就很简单了:

// Create an instance of class Dice named dice
Dice dice = new Dice();

// call the method on the instance you just created
dice.roll();

另外,请参阅 Sun's documentation 并尝试示例以了解您的情况。

修订以匹配您的更改:

public class Risk
{
   public static void IdiceRoll(Dice o)
   {
      o.roll();
   }
}

【讨论】:

  • 对不起,我应该在问题中更清楚。我正在调用此方法的方法将名为 o 的 Dice 作为参数,因此不需要创建 Dice。同样在 dice.roll 中 Dice 不需要大写吗?
  • @David 我更新以显示您描述的情况。不,调用方法时必须使用变量名,而不是名,即Dice。唯一不正确的情况是您调用的方法是 static 方法,但您现在不需要担心。
  • @David,这里给出的是正确的。当您尝试调用对象方法(o.roll(),如果参数定义为 Dice o;或 dice.roll(),如果变量在本地定义为乔纳森有)。如果是static,您将使用类名来调用方法。
  • 好的。我认为它适用于非静态方法,因为在未定义的类中调用静态方法时,我总是必须使用类名。为什么不必为非静态方法执行此操作?
  • @David,我会写一个更长的答案。
【解决方案2】:

从您的评论回复看来,您可能不明白static 和非静态方法之间的区别。

要调用静态方法,请使用类和方法名。我们来看一个稍微修改的例子:

public class Dice {

    private static final Random RANDOM = new Random();

    private int sides;

    protected Dice(int sides) {
        this.sides = sides;
    }

    public static Dice create(int sides) {
        return new Dice(sides);
    }

    public int roll() {
        synchronized(RANDOM) {
            return RANDOM.nextInt(sides) + 1;
        }
    }

}

现在,我可以使用static 方法调用表单(类名+方法名)的静态工厂方法创建一个新的Dice

Dice d = Dice.create(6);

但是对于普通方法,您调用它们时与实例化对象相关,因为它们可能会操作与该对象一起存储的数据。在这种情况下,我创建了一个对象,该对象保存在引用变量d 中,并且该对象包含它应该为其生成数字的边数。要调用它,请使用:

int value = d.roll();

与静态方法相比,使用普通方法有很多优点。不要过度使用static 方法。静态方法不是继承的,也不是对象的一部分——它们只是被认为是类的一部分。这就是您使用类名调用静态方法的原因(尽管不幸的是 Java 也允许使用 object.method,但一个好的 IDE 会警告您)。没有相关的内存状态。但是,对象本身也具有内存状态,并且可能有许多具有不同值的类的不同实例。在这里我们可以创建不同的骰子:

Dice six = Dice.create(6);
Dice twenty = Dice.create(20);

// Use the dice for a 1D6 + 1D20 roll.
int value = six.roll() + twenty.roll();

在这个例子中,我在两个不同的对象实例上调用了roll 方法。使用 Dice.roll() 将不起作用,因为必须针对实例调用 roll 方法,以便它知道要为多少边(在这种情况下)进行滚动。

更高级的主题:该静态方法是一个工厂,可以根据边数创建具有不同特征/随机性的子类。例如,稍后我可以创建一个名为 TrickDice 的特殊 Dice 子类,并且任何时候有人要求一个 5 面骰子,他们只需更改 create 方法即可获得其中一个:

public static Dice create(int sides) {
    if (sides == 5)
        return new TrickDice(5);
    else
        return new Dice(sides);
}

这不会改变它的调用方式...

Dice d = Dice.create(5); // This really is a TrickDice

这是static 方法的有效用法之一。同样,虽然不要过度使用静态方法,但在学习语言时尽量使用普通方法。

编辑:我在另一个question 中注意到您使用此方法签名:

public static void printDice (Dice Dice)

在这里,您使用相同的字母大小写命名了类和变量。我在这个问题中解决了这个问题,因为这可能会帮助您解决您在此处表达的一些困惑。您应该注意用于类和变量的名称。奇怪的是,Java 实际上接受了这种语法。第一个Dice 是类名(类型),第二个Dice 是参数名。相反,您应该为变量/参数名称使用小写字母,因此它应该如下所示:

public static void printDice (Dice dice)

那么当您使用对象引用 (dice) 或类名 (Dice) 时,方法内会更加清晰。

另外,这个打印方法可能应该是Dice 类的一个方法。使用 OOP,您应该考虑要求对象自行打印。这允许不同的子类提供不同的方式来打印自己,而无需尝试将所有逻辑放在一个方法中。这是一个过度使用静态方法的例子,它会降低类的价值和灵活性。

【讨论】:

    【解决方案3】:

    你实例化对象,然后调用方法:

    Dice redSparklyPair = new Dice();
    redSparklyPair.roll();
    

    还是我误解了你的问题?

    【讨论】:

      【解决方案4】:

      我不太清楚你在问什么。如果你有一个Dice 类型的对象,你可以这样做

      public class NotDice {
        // ...
        public int method() {
          Dice dice = new Dice();
          dice.roll();
          // ...
        }
        // ...
      }
      

      如果您在Dice 的子类中,则可以使用super 关键字调用超类方法:

      public class WeightedDice extends Dice {
        // ...
        public void roll() {
          // ...
          super.roll();
          // ...
        }
        // ...
      }
      

      superthis 一样,只是它看起来是类层次结构的上一层。据我所知,没有办法调用 specific 超类的方法;你只能向上看一级。不过,这通常就足够了。

      【讨论】:

      • 我调用 roll 的类与定义它的类不同,请参见编辑。对不起
      【解决方案5】:

      对于您最新的问题更新,您只需说o.roll();

      如果这不起作用,请仔细检查 roll() 方法是 publicnot private

      【讨论】:

      • 我只需要做 o.roll,即使 roll 是在一个不同的类中定义的,而不是我调用它的类?
      • 是的。因为您将实例o 告诉roll() 本身。它是一个 Dice,所以它知道它必须执行 Dice 类中定义的 roll()
      • 详细说明:Dice 知道如何执行您在 Dice 类中定义的每个方法。所以一个 Dice 实例知道如何滚动()。作为其中的一部分,除了 Dice 类(以及 Dice 的任何超类)中的那些方法之外,它不能做任何事情。所以你不需要告诉它使用 Dice 类中的roll(),因为这是它唯一可以做的roll()
      【解决方案6】:

      您必须创建Dice 类的实例,然后调用它。

      假设你有一个Game 类:

      class Risk {
          public static void IdiceRoll (Dice o) {
             // You have to roll the dice
             //  The dice already exist, you just... roll it!!
             o.roll();
             // And that's it
          }
       }
      

      Dice 是类的名称,类就像一个模板或蓝图。它定义了一些东西(比如变量和方法)。

      要使用一个类,您通常会从它创建 object。在这种情况下,您可以随意命名您的对象(在这种情况下,它被命名为o

      所以当你声明时:

      Dice o
      

      你是说。有一个名为o 类型为Dice 的变量,然后编译器知道可以从该对象调用哪些属性和方法。

      如您所见,要在对象上调用方法,您使用. 和方法名称,后跟其参数(如果有的话)

       o.roll();
      

      这就是 instance(非静态)方法的工作原理

      静态(正式的类方法)方法,在类本身中操作,这就是它们不需要实例的原因。

      So, it is possible to invoke them directly:
      
       Risk.IdiceRoll( aDiceInstance );
      

      我认为您真的应该花点时间阅读以下内容:http://java.sun.com/docs/books/tutorial/java/concepts/ 并了解 Java 如何实现这些概念。

      【讨论】:

      • 我试图调用 roll 的方法将骰子作为参数,所以我不需要先创建骰子的实例。对困惑感到抱歉。请查看我编辑的问题。
      【解决方案7】:
      Dice dice = new Dice();
      dice.roll;
      

      【讨论】:

      • 方法 roll 与我正在执行此操作的类不同。见编辑。
      • -1 对于学习一门语言并询问语法(就像提问者在这里)的人来说,答案中存在语法错误可能弊大于利。
      • 我的错!最近一直在使用 ruby​​。
      【解决方案8】:

      您将必须获得对对象实例的引用,然后调用 roll()

      Dice dice = new Dice();
      dice.roll();
      

      【讨论】:

      • 我调用 roll 的类与定义它的类不同,请参见编辑。
      猜你喜欢
      • 2016-10-11
      • 1970-01-01
      • 1970-01-01
      • 2016-07-31
      • 2013-06-08
      • 1970-01-01
      • 1970-01-01
      • 2012-06-25
      • 1970-01-01
      相关资源
      最近更新 更多