续《JAVA编程思想》学习备忘(第277页Polymorphism-1)
Pitfall:"overriding" private methods
以下这个例子是重写了私有的方法吗?
public class PrivateOverride {
}
public class Derived extends PrivateOverride {
}
输出:
private f()
正如标题,它是一个“陷阱”。
The result of this is that only non-private methods may be overriden,but you should watch out for the appearance of overriding private methods,which generates no compiler warnings,but doesn't do what you might expect.To be clear,you should use a different name from a private base-class method in your derived class.
Pitfall:fields and static methods
only ordinary method calls can be polymorphic.
示例:
class Sub extends Super {
}
class Super {
}
public class FieldAccess {
}
输出:
sup.field = 0, sup.getField() = 1
sub.field = 1, sub.getField() = 1, sub.getSuperField() = 0
When a Sub object is upcast to a Super reference,any field accesses are resolved by the compiler,and are thus not polymorphic.In this example,different storage is allocated for Supper.field and Sub.field.Thus,Sub actually contains two fields called field:its own and the one that it gets from Super.However,the Super version is not the default that is produced when you refer to field
If a method is static,it doesn't behave polymorphically:
public class StaticSuper {
}
public class StaticSub extends StaticSuper {
}
public class StaticPolymorphism {
}
输出:
Base staticGet()
Dervied dynamicGet()
static methods are associated with the class,and not the individual objects.
Constructors and polymorphism
As usual,constructors are different from other kinds of methods.This is also true when polymorphism is involved.Even though constructors are not polymorphic(they're actually static methods,but the static declaration is implicit),it's important to understand the way constructors work in complex hierarchies and with polymorphism.This understanding will help you avoid unpleasant entanglements.
Order of constructor calls
A constructor for the base class is always called during the construction process for a derived class.
示例:
class Meal {
}
class Bread{
}
class Cheese{
}
class Lettuce{
}
class Lunch extends Meal{
}
class PortableLunch extends Lunch{
}
public class Sandwich extends PortableLunch {
}
输出:
Meal()
Lunch()
PortableLunch()
Bread()
Cheese()
Lettuce()
Sandwich()
试分析程序扫描轨迹:当实例化Sandwich时,先调用基类PortableLunch的构造方法,PortableLunch又先调用其基类Lunch的构造方法,lunch又先调用其基类Meal的构造方法,因此先输出Meal(),再输出Lunch(),再输出PortableLunch(),而后分别先声明并实例化私有成员属性Bread、Cheese、Lettuce,输出Bread()、Cheese()、Lettuce(),最后进入Sandwich构造方法输出:Sandwich()
Inheritance and cleanup
When using composition and inheritance to create anew class,most of the time you won't have to worry about cleaning up;subobjects can usually be left to the garbage collector.If you do have cleanup issues,you mustbe diligent and create a dispose() method(the name I have chose to use here;you may come up with something better)fro your new class.And with inheritance,you must override dispose() in the derived class if you have and special cleanup that must happen as part of garbage collection.When you override dispose() in an inherited class,it's important to remember to call the base-class version of dispose(),since otherwise the base-class cleanup will not happen.The following example demonstrates this:
class Characteristic {
}
class Description{
}
class LivingCreature{
}
class Animal extends LivingCreature{
}
class Amphibian extends Animal{
}
public class Frog extends Amphibian {
}
输出:
Creating Characteristic is alive
Creating Description Basic Living Creature
LivingCreature()
Creating Characteristic has heart
Creating Description Animal not Vegetable
Animal()
Creating Characteristic can live in water
Creating Description Both water and land
Amphibian()
Creatin Characteristic Croaks
Creating Descripton Eats Bugs
Frog()
Bye!
Frog dispose
disposing Description Eats Bugs
disposing Characteristic Croaks
Amphibian dispose
disposing Description Both water and land
disposing Characteristic can live in water
Animal dispose
disposing Description Animal not Vegetable
disposing Characteristic has heart
LivingCreature dispose
disposing Description Basic Living Creature
disposing Characteristic is alive
需要注意:dispose()方法中,无论t.dispose()还是p.dispose(),都是本类中当前对象的调用(由于Frog对象控制其成员对象,所以未被“垃圾回收”),因此,方法中s字符串也为当前类中所传的内容。
示例:
class Shared {
}
class Composing{
}
public class ReferenceCounting {
}
输出:
Creating Shared 0
Creating Composing 0
Creating Composing 1
Creating Composing 2
Creating Composing 3
Creating Composing 4
disposing Composing 0
disposing Composing 1
disposing Composing 2
disposing Composing 3
disposing Composing 4
Disposing Shared 0