黑马程序员技术交流社区
标题:
父类引用指向子类对象的问题
[打印本页]
作者:
武超
时间:
2011-12-5 19:14
标题:
父类引用指向子类对象的问题
本帖最后由 武超 于 2011-12-6 22:49 编辑
父类引用指向子类对象是这个样子的Fu f=new Zi(); 可是这个父类引用指向子类对象意思是在用父类f调用方法是时候只能调用子类中包含的方法,而且还是父类中必须包含的方法,不能调用子类特有的方法,这样解释对吗?
父类引用指向子类对象 这样的调用形式,在什么情况下使用?
作者:
段波
时间:
2011-12-5 19:54
public class Test {
public static void main(String[] args) {
//这是多态的一些规范吧,用父类引用子类,调用的是子类覆盖父类的那个方法,即方法是可以覆盖的
Father myfather = new Son();
Son son = new Son();
//而直接得到属性还是调到的父类的属性
System.out.println(myfather.str );
System.out.println(myfather.getStr());
myfather.a();
son.b();
}
}
//父类:
class Father {
String str = "这是父类的属性";
public String getStr(){
return str;
};
public void a(){
System.out.print ("这是父类的方法");
}
}
//子类:
class Son extends Father {
String str = "这是子类的属性";
public String getStr(){
return str;
}
public void a(){
System.out.println("这是子类的方法");
}
public void b(){
System.out.println("这是子类的方法");
}
}
复制代码
用代码运行一下就可以看得很明白
作者:
fly51888
时间:
2011-12-5 20:00
本帖最后由 fly51888 于 2011-12-5 20:07 编辑
嗯,理解的很到位。如果想调用子类中特有的方法,则必须把需要调用子类方法的父类强制转换成子类。
如下代码:
public class App extends Person{
public static void main(String[] args) {
Person p = new App();
p.change();
((App) p).sum();
Person p2 = new Person();;
p2.change();
}
public void change(){
System.out.println("App");
}
public void sum(){
System.out.println("sum");
}
}
class Person{
public void change(){
System.out.println("Person");
}
}
其中子类和父类都有change()函数,父类引用可以指向子类对象new App();如:p。
也可以指向父类对象new Person();如:p2。当引用指向子类时调用的是子类的方法,
当指向父类时调用的是父类的方法。当调用子类中的sum()函数时,此时p不能直接调用sum(),
必须将p转换成子类App时才能调用sum();函数。
作者:
刘海涛
时间:
2011-12-5 20:02
本帖最后由 刘海涛 于 2011-12-5 22:25 编辑
只能调用子类中包含的方法,而且还是父类中必须包含的方法,不能调用子类特有的方法,这样解释对吗?
答:错了。只要子类都的方法就能调用。在编译的时候我们只能按照的规定只能调用父类的方法,你申明的是父类对象,编译器给你看到是父类的方法,但是new的是子类,实际的方法是存在的。我们可以通过反射或者强转去调用,new的是什么就是什么对象。
例如:看下面代码:
/**
* Person
* @author Administrator
*
*/
public class Person extends Object {
private String name = "wangwu";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
import java.lang.reflect.Method;
public class Student extends Person {
private int age = 25;
public int getAge() {
return age;
}
public static void main(String[] args) throws Exception, NoSuchMethodException {
Person person = new Student();
System.out.println(person.getName());//默认
System.out.println(((Student)person).getAge());//强转
/**
* 下面是用反射的方式去执行
*/
Method method = person.getClass().getMethod("getAge", null);
System.out.println(method.invoke(person, null));
}
}
复制代码
父类引用指向子类对象 这样的调用形式,在什么情况下使用?
为什么要父类引用指向子类对象呢?例如,现在需求是要打印老师和学生的姓名,但是打印老师是:Teacher:
姓名,学生: Student :姓名 的形式打印,但是现在只有一个方法,不可以去判断是否是老师还是学生。这个时候我们需要用父类引用指向子类对象。
下面看代码:
/**
* Person
* @author Administrator
*
*/
public class Person extends Object {
protected String name;
public String getName() {
return null;
}
public void setName(String name) {
this.name = name;
}
}
/**
* Teacher
* @author Administrator
*
*/
public class Teacher extends Person{
public Teacher(String name) {
setName(name);
}
@Override
public String getName() {
return "Teacher:" + name;
}
}
/**
* Student
* @author Administrator
*
*/
public class Student extends Person {
public Student(String name) {
setName(name);
}
@Override
public String getName() {
return "Student:" + name;
}
public static void main(String[] args) throws Exception, NoSuchMethodException {
Person student = new Student("wangwu");
Person teacher = new Teacher("lisi");
printPersonName(student);//输出Student:wangwu
printPersonName(teacher);//输出Teacher:lisi
}
public static void printPersonName(Person person) {
System.out.println(person.getName());
}
}
复制代码
上面的代码printPersonName()方法 只是打印person getName方法返回的字符串,但是不同的子类是有不同的输
出,这样我们不需要去判断是Student 还是Teacher ,具体的getName 由类自己去完成。这样给我们程序带来极
大的扩展性和维护性。
父类的getName返回为空,这个话毫无意义,这时候其实我们可以将它写出抽象的,具体的实现由子类去实现,
java提供的abstract 方法,如果类中有abstract的方法,特殊的方法不必写方法的实现,那么该类必须修饰为
abstract的,下面是改造后Person的代码:
/**
* Person
* @author Administrator
*
*/
public abstract class Person extends Object {
protected String name;
public abstract String getName();
public void setName(String name) {
this.name = name;
}
}
复制代码
又例如台式电脑的PCI卡插槽,可以插独立声卡,独立显卡,独立网卡等等。在这样的情况下主板厂家需要知道每个卡是怎么执行的过程吗?不需要,生产卡的厂商只需要根据PCI的规范去生产就可以了。具体的实现由每个卡的厂商去实现。就像我们打印person 的getName,我们不需要知道是什么对象。
张老师的视频记得在基础视频中也写过PCI卡的类,你可以去看下,深刻的体会下。这样对后面的面向接口的编程更有帮助(其实就是特殊的父类而已)。
父类引用指向子类对象这样的调用形式当你只知道某种标准(就像Studnet和Teacher只知道getName方法),具体的实现需要子类去实现的时候我们会用到。
作者:
刘国辉
时间:
2011-12-5 21:25
父类引用指向子类对象,当调用父类的方法时,如果子类中有覆写,则调用子类的方法;没有则调用父类中的方法
另外子类中新增的方法此时不可见(如你在C类中增加一个方法F(),则r=c后,r.F()将出错)
A r;
B b = new B();
r = b;
此时r为A类型的引用,但它指向的对象是B类的对象,也就是子类对象
至于好处,你可以看看书,多态的用处
举个经典的例子吧:
Class Shape{
public void draw()
{
}
}
Class A1 extends Shape
{
public void draw()
{
}
}
Class A2 extends Shape
{
public void draw()
{
}
}
每种形状都可以画,如三角形,正方形等等,但每种形状的画法又不一样
有如下方法
public void drawShape(Shape shape)
{
shape.draw();
}
则该方法可以根据你实际传进来的对象调用相应的方法
比如:drawShape(new A1()),此时shape指向A1对象,则shape.draw()调用A1中的draw()
drawShape(new A2()),此时shape指向A2对象, 则shape.draw()调用A2中的draw()
如果A1 A2中没有重写draw(),都将调用Shape中的 draw()
第一次回答这么长,好象有点乱,不知道你能看懂不
作者:
周敏2011nc
时间:
2011-12-6 11:18
继承的好处 : 通过继承,子类中不用写任何代码,就可拥有父类中公有的方法,如果你有自己的实现,可直接@Override,如果有新的方法,可直接写在子类中。
父类引用指向子类对象 :可以说它既是父类的对象,也是子类的对象,当然只能访问父类中公用的方法,如此你在使用父类引用指向子类对象时,应注意是否会用到子类所特有的方法,如果会用到就不应该使用。
作者:
刘海涛
时间:
2011-12-7 07:59
只能调用子类中包含的方法,而且还是父类中必须包含的方法,不能调用子类特有的方法,这样解释对吗?
答:错了。只要子类都的方法就能调用。在编译的时候我们只能按照的规定只能调用父类的方法,你申明的是父类对象,编译器给你看到是父类的方法,但是new的是子类,实际的方法是存在的。我们可以通过反射或者强转去调用,new的是什么就是什么对象。
例如:看下面代码:
/**
* Person
* @author Administrator
*
*/
public class Person extends Object {
private String name = "wangwu";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
import java.lang.reflect.Method;
public class Student extends Person {
private int age = 25;
public int getAge() {
return age;
}
public static void main(String[] args) throws Exception, NoSuchMethodException {
Person person = new Student();
System.out.println(person.getName());//默认
System.out.println(((Student)person).getAge());//强转
/**
* 下面是用反射的方式去执行
*/
Method method = person.getClass().getMethod("getAge", null);
System.out.println(method.invoke(person, null));
}
}
复制代码
父类引用指向子类对象 这样的调用形式,在什么情况下使用?
为什么要父类引用指向子类对象呢?例如,现在需求是要打印老师和学生的姓名,但是打印老师是:Teacher:
姓名,学生: Student :姓名 的形式打印,但是现在只有一个方法,不可以去判断是否是老师还是学生。这个时候我们需要用父类引用指向子类对象。
下面看代码:
/**
* Person
* @author Administrator
*
*/
public class Person extends Object {
protected String name;
public String getName() {
return null;
}
public void setName(String name) {
this.name = name;
}
}
/**
* Teacher
* @author Administrator
*
*/
public class Teacher extends Person{
public Teacher(String name) {
setName(name);
}
@Override
public String getName() {
return "Teacher:" + name;
}
}
/**
* Student
* @author Administrator
*
*/
public class Student extends Person {
public Student(String name) {
setName(name);
}
@Override
public String getName() {
return "Student:" + name;
}
public static void main(String[] args) throws Exception, NoSuchMethodException {
Person student = new Student("wangwu");
Person teacher = new Teacher("lisi");
printPersonName(student);//输出Student:wangwu
printPersonName(teacher);//输出Teacher:lisi
}
public static void printPersonName(Person person) {
System.out.println(person.getName());
}
}
复制代码
上面的代码printPersonName()方法 只是打印person getName方法返回的字符串,但是不同的子类是有不同的输
出,这样我们不需要去判断是Student 还是Teacher ,具体的getName 由类自己去完成。这样给我们程序带来极
大的扩展性和维护性。
父类的getName返回为空,这个话毫无意义,这时候其实我们可以将它写出抽象的,具体的实现由子类去实现,
java提供的abstract 方法,如果类中有abstract的方法,特殊的方法不必写方法的实现,那么该类必须修饰为
abstract的,下面是改造后Person的代码:
/**
* Person
* @author Administrator
*
*/
public abstract class Person extends Object {
protected String name;
public abstract String getName();
public void setName(String name) {
this.name = name;
}
}
复制代码
又例如台式电脑的PCI卡插槽,可以插独立声卡,独立显卡,独立网卡等等。在这样的情况下主板厂家需要知道每个卡是怎么执行的过程吗?不需要,生产卡的厂商只需要根据PCI的规范去生产就可以了。具体的实现由每个卡的厂商去实现。就像我们打印person 的getName,我们不需要知道是什么对象。
张老师的视频记得在基础视频中也写过PCI卡的类,你可以去看下,深刻的体会下。这样对后面的面向接口的编程更有帮助(其实就是特殊的父类而已)。
父类引用指向子类对象这样的调用形式当你只知道某种标准(就像Studnet和Teacher只知道getName方法),具体的实现需要子类去实现的时候我们会用到。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2