为什么方法可以被覆盖但变量不能被覆盖?

时间:2016-08-04 07:22:26

标签: java

代码:

import random

class Potion:
    """Define the Potion class. Could be explosive and provoke a damage"""
    def __init__(self, explosive=None, damage=None):
        if explosive == None:
            self.__explosive = bool(random.getrandbits(1))
        else:
            self.__explosive = explosive

        if self.__explosive:
            if damage == None:
                self.__damage = random.randint(1,5)
            else:
                self.__damage = damage
        else:
            self.__damage = 0

    def isExplosive(self):
        return self.__explosive

    def explode(self):
        if self.isExplosive():
            return self.__damage
        else:
            return 0

    def __str__(self):
        if self.isExplosive():
            res = "explosive potion"
        else:
            res = "simple potion"
        return res

class Hero:
    """Simple Hero class"""
    def __init__(self, name):
        self.__name = name
        self.__hp = 100
        self.__potions = []

    def receiveDamage(self, damage):
        self.__hp = self.__hp - damage
        if self.__hp <= 0:
            print("I'm dead!")

    def isAlive(self):
        return self.__hp > 0

    def getPotion(self, room):
        """ Get the first potion in the room.If the potion 
            is explosive, explode and receive some damage
            TODO: Trapped potions?
        """
        potion = room.getFirstPotion()
        print("%s take a %s" % (self.__name, potion))
        if potion.isExplosive():
            damage = potion.explode()
            print("%s received %d hp of damage!!" % (self.__name, damage))
            self.receiveDamage(damage)
        else:
            self.__potions.append(potion)

    def __str__(self):
        res = "%s have %d HP and %d potions." % (self.__name, self.__hp, len(self.__potions))
        return res

class Room:
    def __init__(self, potions):
        """Create a room with some potions"""
        self.__potions = potions

    def getFirstPotion(self):
        """Return the first potion """
        if self.__potions:
            potion = self.__potions.pop()
        else:
            potion = None
        return potion 

    def havePotions(self):
        return len(self.__potions) > 0

    @property
    def potions(self):
        return self.__potions

    def __str__(self):
        return "This room have %s potions" % len(self.__potions)

peter = Hero('Peter')
room = Room(potions=[Potion() for i in range(5)])
print(room)
print(peter)

while room.havePotions():
    print("___________")
    peter.getPotion(room)
    print(room)
    print(peter)
  

输出:

     

2

     

5

     

内部方法1 test2

     

Inside method2 test1

问题:

为什么只覆盖方法,但变量保持不变?

此行为是否有名称? (比如&#34;覆盖&#34;方法)

4 个答案:

答案 0 :(得分:2)

覆盖方法意味着让同一个方法调用执行另一个方法体(在子类中)。

对于变量&#34;覆盖&#34;是不必要的:您可以覆盖变量的值。

在子类中声明具有相同名称的变量隐藏父类变量并引入一个额外的字段。

对于可覆盖的方法,需要一种特殊的机制,以便代码中的位置可以调用对象的实际类指定的方法。这与访问字段相反。

答案 1 :(得分:1)

这里发生的事情是您使用type1引用指向test2的实例。您可以这样做,因为test2是一种test1 - 这称为多态

test2派生自test1,因此当您创建test2类型的对象时,您基本上会创建两个对象test2test1(它不会作为自治对象驻留在堆中。)

JVM将从其引用访问对象的字段(因为Java是一种静态类型语言)。

所以,虽然test2 隐藏两个test1字段,但当尝试从test1引用访问它们时,Java会自动转到test1 }。

关于这些领域的说法。

在处理方法时,我们遇到了一个更复杂的问题。方法是重写,因此,在构建方法表时,test2的方法会覆盖test1的方法。但是,静态方法不是实例方法。

因此,当尝试从method2的引用中访问test2的静态方法test1时,您正在&#34;滥用&#34;代码。你应该做的是打电话test1.method2(),或者,如果你想访问test2的静态方法,你应该使用test2.method2()

希望我解释得很好......

答案 2 :(得分:0)

在上面的示例中,您正在创建基类的引用,它将获取值A = 2,B = 5并且它也将分配内存。因此,当覆盖到派生类时,基类变量隐藏派生类变量值& #39;为什么它不能在派生类中重写。

答案 3 :(得分:0)

符合:System.out.println(cc.A);
这不是调用静态成员的正确方法,您应该始终使用类名,例如:System.out.println(test1.A);

根据Java规范,实例变量在扩展时不会被子类从超类中重写。
变量是静态的还是非静态的。只能覆盖方法。 这就是cc.A&amp;的输出的原因。 cc.B来自test1

方法覆盖:
此处覆盖的代码cc.method1();发生,对象类型(即类的实例)实际上确定在运行时选择了哪个方法,在此代码中通过new test2()的此对象声明:{{1} }
编译器首先检查test1 cc = new test2();类中的方法然后检查test1类中的方法,如果所有签名(参数,返回类型等)相同则调用子类方法 因为它覆盖了基类方法,因为实际对象属于类text2

对于静态方法: 静态方法无法被覆盖,因为方法覆盖仅发生在方法的动态(即运行时)查找的上下文中 静态方法(按名称)静态查找(即在编译时) 这就是为什么输出来自类test2

对于Java中的“静态方法”,在编译时确定要调用的确切方法 您明确指定了要执行其静态方法的类的名称