[size=medium]
[b]1. 多态概念要点:[/b]
概念:
类重载(overload)方法,子类覆盖(override)父类的方法都是多态的体现.
多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。
引用Charlie Calverts对多态的描述——多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自“Delphi4 编程技术内幕”)。
简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。
作用:
把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。也就是说,父亲的行为像儿子,而不是儿子的行为像父亲。
[color=red]结论一:多态时,当子类覆盖了父类的方法,使用子类覆盖的方法
结论二:当子类覆盖父类的成员变量时,父类方法使用的是父类的成员变量,子类方法使用的是子类的成员变量[/color]
[/size]
[size=medium]
output:
101
101
[color=red]super number:101
301[/color]
super number:102
102
[b]2. super关键字使用要点:[/b]
结论一:构造函数里面通过super调用父类的构造函数的语句只能放置在第一行,否则编译报错.
结论二:如果子类里面有和父类同名的属性和方法(构造函数除外),则父类的同名属性和方法在子类中会被覆盖,子类里面可以通过super.propertyName和super.methodName的方式来访问父类中被覆盖的属性和方法,当然前提是父类的属性和方法不是private的,不过对于属性你可以说子类覆盖了父类的同名属性,也可以说子类没有覆盖,因为就算子类覆盖了属性,如果运行时的instance调用的是方法是继承自父类的,那么该方法访问的是父类的同名属性,不是子类的,子类的方法访问的是子类的属性,如上面的s3打印的是[super number:101,301].
结论三:子类里面的普通方法super.methodName的位置不需要是第一行,这跟构造函数不同.
[b]3. 构造函数定义要点:[/b]
1)如果一个类没有定义任何构造函数,编译器默认会生成一个无参构造函数
2)如果一个类显示了定义的有参构造函数,那么编译器就不会生成无参构造函数,如果此时你需要无参构造函数,你得显示的定义一个无参构造函数
3)子类的构造函数是一定要调用父类的构造函数的,如果子类的构造函数中没写任何调用父类的构造函数的代码,那么其实隐含者子类会调用父类的无参构造函数,所以这个时候父类必须要有无参构造函数存在
4)父类如果没有定义任何构造函数,编译器默认会给父类生成一个无参构造函数,这种情况下,子类的构造函数没有任何约束,你可以不定义,也可以显示的定义
5)父类如果定义了有参构造函数,而没有显示定义无参构造函数的话,那么子类的构造函数中必然也要显示的调用父类的有参构造函数,子类中不能省略调父类构造函数的代码
[/size]
[b]1. 多态概念要点:[/b]
概念:
类重载(overload)方法,子类覆盖(override)父类的方法都是多态的体现.
多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。
引用Charlie Calverts对多态的描述——多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自“Delphi4 编程技术内幕”)。
简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。
作用:
把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。也就是说,父亲的行为像儿子,而不是儿子的行为像父亲。
[color=red]结论一:多态时,当子类覆盖了父类的方法,使用子类覆盖的方法
结论二:当子类覆盖父类的成员变量时,父类方法使用的是父类的成员变量,子类方法使用的是子类的成员变量[/color]
[/size]
class SuperClass {
int number;
public SuperClass(int number) {
this.number = number;
}
public int getNumber() {
return ++number;
}
}
class SubClass1 extends SuperClass {
public SubClass1(int number) {
super(number);
}
}
class SubClass2 extends SuperClass {
int number=200;
public SubClass2(int number) {
super(number);
}
}
class SubClass3 extends SuperClass {
int number=300;
public SubClass3(int number) {
super(number);
}
public int getNumber() {
System.out.println("super number:"+super.getNumber());
return ++number;
}
}
class SubClass4 extends SuperClass{
public SubClass4(int number){
super(number);
}
public int getNumber() {
System.out.println("super number:"+super.getNumber());
return ++number;
}
}
public class TestPolymorphsim {
public static void main(String[] args) {
SuperClass s1 = new SubClass1(100);
SuperClass s2 = new SubClass2(100);
SuperClass s3 = new SubClass3(100);
SuperClass s4 = new SubClass4(100);
System.out.println(s1.getNumber()+"\n");
System.out.println(s2.getNumber()+"\n");
System.out.println(s3.getNumber()+"\n");
System.out.println(s4.getNumber());
}
}
[size=medium]
output:
101
101
[color=red]super number:101
301[/color]
super number:102
102
[b]2. super关键字使用要点:[/b]
结论一:构造函数里面通过super调用父类的构造函数的语句只能放置在第一行,否则编译报错.
结论二:如果子类里面有和父类同名的属性和方法(构造函数除外),则父类的同名属性和方法在子类中会被覆盖,子类里面可以通过super.propertyName和super.methodName的方式来访问父类中被覆盖的属性和方法,当然前提是父类的属性和方法不是private的,不过对于属性你可以说子类覆盖了父类的同名属性,也可以说子类没有覆盖,因为就算子类覆盖了属性,如果运行时的instance调用的是方法是继承自父类的,那么该方法访问的是父类的同名属性,不是子类的,子类的方法访问的是子类的属性,如上面的s3打印的是[super number:101,301].
结论三:子类里面的普通方法super.methodName的位置不需要是第一行,这跟构造函数不同.
[b]3. 构造函数定义要点:[/b]
1)如果一个类没有定义任何构造函数,编译器默认会生成一个无参构造函数
2)如果一个类显示了定义的有参构造函数,那么编译器就不会生成无参构造函数,如果此时你需要无参构造函数,你得显示的定义一个无参构造函数
3)子类的构造函数是一定要调用父类的构造函数的,如果子类的构造函数中没写任何调用父类的构造函数的代码,那么其实隐含者子类会调用父类的无参构造函数,所以这个时候父类必须要有无参构造函数存在
4)父类如果没有定义任何构造函数,编译器默认会给父类生成一个无参构造函数,这种情况下,子类的构造函数没有任何约束,你可以不定义,也可以显示的定义
5)父类如果定义了有参构造函数,而没有显示定义无参构造函数的话,那么子类的构造函数中必然也要显示的调用父类的有参构造函数,子类中不能省略调父类构造函数的代码
[/size]