学习和使用继承时最先要清楚的三点
2004-03-30 19:16
633 查看
作者:qlampskyface
和作者联系:xiaozuidaizhi@sina.com
第一点:
那就是
1.如果该子类覆盖了父类的方法,那么该子类对象调用该方法时,被该方法修改的类级别变量是该子类的变量。
2.如果该子类没有覆盖父类方法,而直接调用父类的方法,那么被该方法修改的类级别变量是父类的变量。
1则如下例:
public class Temp{
public static void main(String args[]){
b bb = new b();
bb.fuqin();
}
}
class a{
public String s = "fuqin";
public void fuqin(){
System.out.println(s);
}
}
class b extends a{
public String s = "erzi";
public void fuqin(){
System.out.println(s);
}
}
//结果为erzi
2.则如下例:
public class Temp{
public static void main(String args[]){
b bb = new b();
bb.fuqin();
}
}
class a{
public String s = "fuqin";
public void fuqin(){
System.out.println(s);
}
}
class b extends a{
public String s = "erzi";
public void erzi(){
System.out.println(s);
}
}
//结果为fuqin
第二点:
那就是对“覆盖(override)”和“重载(overload)”以及重建的概念的清晰。
先声明一下:重建就是写一个新的方法。
如下例:
下面这个叫覆盖
public class Temp {
public static void main(String[] args) {
Sub sub = new Sub();
sub.plus(2);
System.out.println(sub.i);
}
}
class Super {
protected int i;
void plus(int i) {
this.i += i;
}
}
class Sub
extends Super {
protected int i = 1;
void plus(int i){
this.i=i+5;
}
}
下面这个叫重建,不是重载:
public class Temp {
public static void main(String[] args) {
Sub sub = new Sub();
sub.plus(2);
sub.plus(2,2);
System.out.println(sub.i);
System.out.println(((Super)sub).i);
}
}
class Super {
protected int i;
void plus(int i) {
this.i += i;
}
}
class Sub
extends Super {
protected int i = 1;
void plus(int i,int j){
this.i=i+j;
}
}
第三点:
那就是通常所说的“继承后使用多态”、“动态方法调度”、“运行时类型识别”了。先不要被上面的术语搞昏头哦:-)
可以总结为以下两条:
1.默认状态(和强制类型转换状态相区别)下,该对象(sub)只能调用父类方法和父类变量(调用该子类方法时会出现编译期错误)。此种情况下,还有两种不同的情况:
▲被调用方法是被该子类覆盖的方法,这时其实是显式调用父类方法,实际上是调用该子类方法和该子类变量,这时父类变量不能被该方法修改,被修改的是该子类变量。
▲被调用方法没有被该子类覆盖,这时是调用父类方法,父类变量可以被该方法修改。
看看下面的代码,注意1~5处。
public class Temp {
public static void main(String[] args) {
Super sub = new Sub();
System.out.println(sub.i);//打印结果为0----------------------------------------------1
sub.plus(3);//打印结果为Sub's plus.默认状态下伪调用被覆盖了的父类方法,
//实际调用该子类该方法------------------------------------------------------2
System.out.println(sub.i);//打印结果为0----------------------------------------------3
sub.print();//打印结果为Super.默认状态下调用没有被覆盖的父类方法
//实际就是本类(父类)方法-------------------------------------------------4
System.out.println(sub.i);//打印结果为5:---------------------------------------------5
}
}
class Super {
protected int i=0;
void plus(int i) {
this.i =3;
System.out.println("Super's plus");
}
void print(){
this.i=5;
System.out.println("Super");
}
}
class Sub
extends Super {
protected int i = 1;
void plus(int i) {
this.i = i + 8;
System.out.println("Sub's plus");
}
void plus(int i, int j) {
this.i = i + j;
}
}
2.强制类型转换状态下【注1】,该对象(sub)既可以调用该子类方法,又可以调用没有被覆盖的父类方法。
看看下面的代码,注意6、7处:
public class Temp {
public static void main(String[] args) {
Super sub = new Sub();
((Sub)sub).plus(3);//调用方法时强制转换----------------------------------------------6
((Sub)sub).print();//调用没有被覆盖的父类方法,改变父类变量---------------7
}
}
class Super {
protected int i=0;
void plus(int i) {
this.i =3;
System.out.println("Super's plus :"+this.i);
}
void print(){
this.i=5;
System.out.println("Super's print");
}
}
class Sub
extends Super {
protected int i = 1;
void plus(int i) {
this.i = i + 8;
System.out.println("Sub's plus :"+this.i);
}
}
【注1】对父类强制转换的结果和默认状态下是相同的,即使是被覆盖的方法,以父类做强制转换后的结果仍是实际上调用了该子类方法和该子类变量。所以,这里只讨论对该子类强制转换。
对第三点小结如下:
1.如果要想调用该子类的覆盖了父类的方法,可以在默认状态下调用,也可以在强制转换后调用。因为无论是在默认状态下,还是用父类去做强制转换调用,或者是用该子类去做强制转换调用,结果都是一样的,即调用被覆盖的该子类的方法;
2.如果要想调用父类的没有被该子类覆盖的方法,可以在默认状态下调用,也可以在被该子类强制转换后调用。都是一样的。
3.如果要想调用父类的被该子类覆盖的方法,对不起,这种情况下你得不到,不过可以通过“父类 对象名 = new 父类()”的普通创建方式得到。
4.如果要想调用父类变量(属性),对于所有的父类变量(属性),在默认状态下即可调用;对于没有被该子类覆盖的变量(属性),也可以在被子类强制转换后调用;
5.如果要想调用该子类特有的变量(属性),则只能在用该子类强制状态的情况下调用。
6.如果要想调用该子类特有的方法,则只能在用该子类强制状态的情况下使用。
下面的例子混合了上述情况,体验一下。
public class Temp {
public static void main(String[] args) {
Super sub = new Sub();
//调用父类特有的方法
System.out.println("父类特有的方法");
sub.print();
((Super)sub).print();
((Sub)sub).print();
//调用父类特有的变量(属性)
System.out.println("父类特有的变量(属性)");
System.out.println(sub.supown);
System.out.println(((Sub)sub).supown);
//调用被覆盖的父类的方法
System.out.println("被覆盖的父类的方法");
Super sup = new Super();
sup.plus(3);
//调用被覆盖了的父类的变量(属性)
System.out.println("被覆盖了的父类的变量(属性)");
System.out.println(sub.i);
System.out.println(sub.both);
//调用子类特有的方法
System.out.println("子类特有的方法");
((Sub)sub).reduce(3);
//调用子类特有的变量(属性)
System.out.println("子类特有的变量(属性)");
System.out.println(((Sub)sub).subown);
//调用覆盖了父类的子类的方法
System.out.println("覆盖了父类的子类的方法");
sub.plus(3);
((Sub)sub).plus(3);
((Super)sub).plus(3);
//调用被覆盖的子类的方法
System.out.println("覆盖了父类的子类的变量(属性)");
System.out.println(((Sub)sub).i);
System.out.println(((Sub)sub).both);
}
}
class Super {
protected int i = 0;
String both="Super's both",supown="Super's own supown";
void plus(int i) {
System.out.println("Super's plus");
}
void print() {
System.out.println("Super's own print");
}
}
class Sub
extends Super {
protected int i = 1;
String both="Sub's both",subown="Sub's own subown";
void plus(int i) {
System.out.println("Sub's plus");
}
void plus(int i, int j) {
System.out.println("Sub's own plus");
}
void reduce(int i) {
System.out.println("Sub's own reduce");
}
}
结果如下:
父类特有的方法
Super's own print
Super's own print
Super's own print
父类特有的变量(属性)
Super's own supown
Super's own supown
Super's own supown
被覆盖的父类的方法
Super's plus
被覆盖了的父类的变量(属性)
0
Super's both
子类特有的方法
Sub's own reduce
子类特有的变量(属性)
Sub's own subown
覆盖了父类的子类的方法
Sub's plus
Sub's plus
Sub's plus
覆盖了父类的子类的变量(属性)
1
Sub's both
对第三点总结如下:
通过以上的例子,我们可以得出以下总结:
对于以这种方式创建的对象来说,除了被子类[/b]
覆盖的父类方法外,它能访问子类和父类的其[/b]
余全部属性及方法。对子类的其余部分调用要[/b]
在强制转换后进行(除去继承自父类的方法)[/b][/b]
请看到的朋友评论!
和作者联系:xiaozuidaizhi@sina.com
第一点:
那就是
1.如果该子类覆盖了父类的方法,那么该子类对象调用该方法时,被该方法修改的类级别变量是该子类的变量。
2.如果该子类没有覆盖父类方法,而直接调用父类的方法,那么被该方法修改的类级别变量是父类的变量。
1则如下例:
public class Temp{
public static void main(String args[]){
b bb = new b();
bb.fuqin();
}
}
class a{
public String s = "fuqin";
public void fuqin(){
System.out.println(s);
}
}
class b extends a{
public String s = "erzi";
public void fuqin(){
System.out.println(s);
}
}
//结果为erzi
2.则如下例:
public class Temp{
public static void main(String args[]){
b bb = new b();
bb.fuqin();
}
}
class a{
public String s = "fuqin";
public void fuqin(){
System.out.println(s);
}
}
class b extends a{
public String s = "erzi";
public void erzi(){
System.out.println(s);
}
}
//结果为fuqin
第二点:
那就是对“覆盖(override)”和“重载(overload)”以及重建的概念的清晰。
先声明一下:重建就是写一个新的方法。
如下例:
下面这个叫覆盖
public class Temp {
public static void main(String[] args) {
Sub sub = new Sub();
sub.plus(2);
System.out.println(sub.i);
}
}
class Super {
protected int i;
void plus(int i) {
this.i += i;
}
}
class Sub
extends Super {
protected int i = 1;
void plus(int i){
this.i=i+5;
}
}
下面这个叫重建,不是重载:
public class Temp {
public static void main(String[] args) {
Sub sub = new Sub();
sub.plus(2);
sub.plus(2,2);
System.out.println(sub.i);
System.out.println(((Super)sub).i);
}
}
class Super {
protected int i;
void plus(int i) {
this.i += i;
}
}
class Sub
extends Super {
protected int i = 1;
void plus(int i,int j){
this.i=i+j;
}
}
第三点:
那就是通常所说的“继承后使用多态”、“动态方法调度”、“运行时类型识别”了。先不要被上面的术语搞昏头哦:-)
可以总结为以下两条:
1.默认状态(和强制类型转换状态相区别)下,该对象(sub)只能调用父类方法和父类变量(调用该子类方法时会出现编译期错误)。此种情况下,还有两种不同的情况:
▲被调用方法是被该子类覆盖的方法,这时其实是显式调用父类方法,实际上是调用该子类方法和该子类变量,这时父类变量不能被该方法修改,被修改的是该子类变量。
▲被调用方法没有被该子类覆盖,这时是调用父类方法,父类变量可以被该方法修改。
看看下面的代码,注意1~5处。
public class Temp {
public static void main(String[] args) {
Super sub = new Sub();
System.out.println(sub.i);//打印结果为0----------------------------------------------1
sub.plus(3);//打印结果为Sub's plus.默认状态下伪调用被覆盖了的父类方法,
//实际调用该子类该方法------------------------------------------------------2
System.out.println(sub.i);//打印结果为0----------------------------------------------3
sub.print();//打印结果为Super.默认状态下调用没有被覆盖的父类方法
//实际就是本类(父类)方法-------------------------------------------------4
System.out.println(sub.i);//打印结果为5:---------------------------------------------5
}
}
class Super {
protected int i=0;
void plus(int i) {
this.i =3;
System.out.println("Super's plus");
}
void print(){
this.i=5;
System.out.println("Super");
}
}
class Sub
extends Super {
protected int i = 1;
void plus(int i) {
this.i = i + 8;
System.out.println("Sub's plus");
}
void plus(int i, int j) {
this.i = i + j;
}
}
2.强制类型转换状态下【注1】,该对象(sub)既可以调用该子类方法,又可以调用没有被覆盖的父类方法。
看看下面的代码,注意6、7处:
public class Temp {
public static void main(String[] args) {
Super sub = new Sub();
((Sub)sub).plus(3);//调用方法时强制转换----------------------------------------------6
((Sub)sub).print();//调用没有被覆盖的父类方法,改变父类变量---------------7
}
}
class Super {
protected int i=0;
void plus(int i) {
this.i =3;
System.out.println("Super's plus :"+this.i);
}
void print(){
this.i=5;
System.out.println("Super's print");
}
}
class Sub
extends Super {
protected int i = 1;
void plus(int i) {
this.i = i + 8;
System.out.println("Sub's plus :"+this.i);
}
}
【注1】对父类强制转换的结果和默认状态下是相同的,即使是被覆盖的方法,以父类做强制转换后的结果仍是实际上调用了该子类方法和该子类变量。所以,这里只讨论对该子类强制转换。
对第三点小结如下:
1.如果要想调用该子类的覆盖了父类的方法,可以在默认状态下调用,也可以在强制转换后调用。因为无论是在默认状态下,还是用父类去做强制转换调用,或者是用该子类去做强制转换调用,结果都是一样的,即调用被覆盖的该子类的方法;
2.如果要想调用父类的没有被该子类覆盖的方法,可以在默认状态下调用,也可以在被该子类强制转换后调用。都是一样的。
3.如果要想调用父类的被该子类覆盖的方法,对不起,这种情况下你得不到,不过可以通过“父类 对象名 = new 父类()”的普通创建方式得到。
4.如果要想调用父类变量(属性),对于所有的父类变量(属性),在默认状态下即可调用;对于没有被该子类覆盖的变量(属性),也可以在被子类强制转换后调用;
5.如果要想调用该子类特有的变量(属性),则只能在用该子类强制状态的情况下调用。
6.如果要想调用该子类特有的方法,则只能在用该子类强制状态的情况下使用。
下面的例子混合了上述情况,体验一下。
public class Temp {
public static void main(String[] args) {
Super sub = new Sub();
//调用父类特有的方法
System.out.println("父类特有的方法");
sub.print();
((Super)sub).print();
((Sub)sub).print();
//调用父类特有的变量(属性)
System.out.println("父类特有的变量(属性)");
System.out.println(sub.supown);
System.out.println(((Sub)sub).supown);
//调用被覆盖的父类的方法
System.out.println("被覆盖的父类的方法");
Super sup = new Super();
sup.plus(3);
//调用被覆盖了的父类的变量(属性)
System.out.println("被覆盖了的父类的变量(属性)");
System.out.println(sub.i);
System.out.println(sub.both);
//调用子类特有的方法
System.out.println("子类特有的方法");
((Sub)sub).reduce(3);
//调用子类特有的变量(属性)
System.out.println("子类特有的变量(属性)");
System.out.println(((Sub)sub).subown);
//调用覆盖了父类的子类的方法
System.out.println("覆盖了父类的子类的方法");
sub.plus(3);
((Sub)sub).plus(3);
((Super)sub).plus(3);
//调用被覆盖的子类的方法
System.out.println("覆盖了父类的子类的变量(属性)");
System.out.println(((Sub)sub).i);
System.out.println(((Sub)sub).both);
}
}
class Super {
protected int i = 0;
String both="Super's both",supown="Super's own supown";
void plus(int i) {
System.out.println("Super's plus");
}
void print() {
System.out.println("Super's own print");
}
}
class Sub
extends Super {
protected int i = 1;
String both="Sub's both",subown="Sub's own subown";
void plus(int i) {
System.out.println("Sub's plus");
}
void plus(int i, int j) {
System.out.println("Sub's own plus");
}
void reduce(int i) {
System.out.println("Sub's own reduce");
}
}
结果如下:
父类特有的方法
Super's own print
Super's own print
Super's own print
父类特有的变量(属性)
Super's own supown
Super's own supown
Super's own supown
被覆盖的父类的方法
Super's plus
被覆盖了的父类的变量(属性)
0
Super's both
子类特有的方法
Sub's own reduce
子类特有的变量(属性)
Sub's own subown
覆盖了父类的子类的方法
Sub's plus
Sub's plus
Sub's plus
覆盖了父类的子类的变量(属性)
1
Sub's both
对第三点总结如下:
通过以上的例子,我们可以得出以下总结:
对于以这种方式创建的对象来说,除了被子类[/b]
覆盖的父类方法外,它能访问子类和父类的其[/b]
余全部属性及方法。对子类的其余部分调用要[/b]
在强制转换后进行(除去继承自父类的方法)[/b][/b]
请看到的朋友评论!
相关文章推荐
- 用VB.NET和Excel排生产计划--企业信息化探讨之一
- 用VB.NET做个论坛发帖软件
- 软件开发,创意是灵魂——用HttpWebRequest和正则表达式提取网页中的链接
- WinForm中类似WebForm中的CheckBoxList控件
- print a dialog is simple.
- 第一个帖子,先灌灌水
- dudu: 请教一个问题
- VC6 SP6 released!
- 链接管理部分的bug已经修正
- Lunch Subscribe
- Bug报道 (3.30)
- FTP集团在VS Live大会上公布了2004年度读者选择奖
- 自己做一个ExceptionLOG
- 对敏捷开发方法的一些疑问
- Visual Studio .NET已检测到指定的WEB服务运行的不是ASP.NET 1.1版
- .NET Enterprise Services Performance
- add cool toolbar 256corler is easy,only two file and onCreate func is needed also the MainFrame.toolbar must resize to what real need and also the load width is same to it.
- >>CLI里面的秘密……(二)强命名、元数据以及文件结构(上半部分)
- 获得系统异常的详细信息
- 今天才发现,网上误人子弟的事还很多----关于做不规窗体