0

我知道几种编程语言。其中大多数是脚本语言,如 lua、perl、JS、ruby 等。

但最近,我开始使用 Java 进行编程,它运行起来很安静。所以我一直在想JS中存在的某个函数。构造函数的原型,也就是。为了进一步理解我的问题到底是什么,我将在 JS 中做一个例子。假设您要创建一个狗的应用程序。

function dog (){
this.property1 = value;
this.propertr2 = value2;
this.propertyN = valueN;
//etc.
}

//now, I will create several instances of the constructor in JS

var snoopy = new dog();
var buddy = new dog();

我知道的关于 JS 的令人敬畏的部分是,您可以使用以下原型关键字动态更改构造函数的信息以及构造函数的所有实例(在 JS 中调用它):

 dog.prototype.bark = function () {
 console.log("Woof!");
 };

并且 THIS 不仅改变了关于构造函数的信息,因此每只用构造函数创建的狗都会知道如何吠叫,它也改变了,所以构造函数的所有实例都获得了原型插入的信息,在这种情况下,教狗如何吠叫。我们可以在下一个示例中看到:

var someOtherDog = new dog ();
someOtherDog.bark(); //output will be: Woof!
snoopy.bark();       //output will also be: Woof!
buddy.bark();        //you guessed it! it will also be: Woof!

因此,使用 JS 中的这个原型关键字,我可以操作构造函数及其实例。现在,我的问题是:

如何在 java 中操作类及其实例?这甚至可能吗?如果是这样; 我应该怎么做才能在java中做类似的事情?

class dog
{
    private String hairColor;
    public dog ()
    {
        hairColor = "Brown";
    }
    public static void main (String args[])
    {
        dog snoopy = new dog ();
        dog buddy = new dog ();
        //now, how do I manipulate the class like I did in JS?
    }
}
4

3 回答 3

1

问题是 lua 和 JavaScript 都是基于原型的,Java 不是。您可以使用反射来完成类似的事情,但不是在 JavaScript 级别。反射

于 2013-01-06T23:33:34.287 回答
1

JavaScript 中的继承是由原型链完成的。基本上,当bark在对象中找不到时snoopy,会在其原型中查找snoopy.prototype。如果在那里找到,则使用该版本。如果不是(例如在调用 时bark.toString()),则遍历原型链,直到找到具有该成员的原型。原型本身在所有“实例”之间共享,并且由于它只是一个普通对象,您可以稍后添加或删除成员。

Java中的继承是基于类的。除非重新编译并重新加载整个类,否则不能在运行时从类定义中添加或删除成员。这是一种不同的编程范式,这意味着您必须使用其他技术和模式对其进行(稍微)不同的编程。

于 2013-01-06T23:39:20.430 回答
0

如果需要,您可以即时创建匿名类。

假设你有一堂课:

class Dog {
    String name;
    Dog(String name) { this.name = name; }
    void bark() { System.out.println(name + " says 'woof!'"); }

    public static void main(String...args) { 
        Dog snoopy = new Dog("snoopy");
        snoopy.bark();
    }

}

这是结果

c:\files\j>javac Dog.java

c:\files\j>java Dog
snoopy says 'woof!'

现在伙计,他不说 woof - 他说 ruff!所以我们像这样即时创建一个

class Dog {
    String name;
    Dog(String name) { this.name = name; }
    void bark() { System.out.println(name + " says 'woof!'"); }

    public static void main(String...args) { 
        Dog snoopy = new Dog("snoopy");
        snoopy.bark();
        Dog buddy = new Dog("buddy") {
            @Override void bark() { System.out.println(name + " says 'ruff!'"); }
        };
        buddy.bark();
    }

}

这导致

c:\files\j>javac Dog.java

c:\files\j>java Dog
snoopy says 'woof!'
buddy says 'ruff!'

如果你想永久地改变每条狗,那会变得更加困难,但可以通过策略模式来完成。

假设我们有以下内容

abstract class BarkingStrategy {
    public abstract void doBark(Dog dog);
}

class TypicalBarkingStrategy extends BarkingStrategy {
    public void doBark(Dog dog) { System.out.println(dog.getName() + " says 'woof!'"); }
}

class AggressiveBarkingStrategy extends BarkingStrategy {
    public void doBark(Dog dog) { System.out.println(dog.getName() + " says 'Rrrruff!'"); }
}

class Dog {
    // notice this is static - that means it belongs to the class itself, not 
    // any particular instance of it - similar to prototype
    static BarkingStrategy bark = new TypicalBarkingStrategy();
    String name;
    Dog(String name) { this.name = name; }
    String getName() { return name; }
    void bark() { bark.doBark(this); }
}

然后您可以执行以下操作

public static void main(String...args) {
    Dog snoopy = new Dog("snoopy");
    snoopy.bark();
    Dog.bark = new AggressiveBarkingStrategy();
    snoopy.bark();
}

这导致

c:\files\j>javac Dog.java

c:\files\j>java Dog
snoopy says 'woof!'
snoopy says 'Rrrruff!'
于 2013-01-06T23:34:02.493 回答