请教问题父类访问子类问题

问题描述

问题是这样:B继承于A,A有成员i,k B有成员h,gAc=newB();在c中,我能得到h,g吗?有什么办法才能得到h,g?就是要得到子类的成员,如何得到?听说用抽象类可以实现,不知那位高手可以帮我忙?非常感谢!!

解决方案

解决方案二:
按照你的想法多态是不可以的父类本身就没有的东西你还用多态也就调用不到子类的东西要么Bb=newB();多态的话就必须父类中定义一个抽象函数或者虚函数然后让子类去实现abstractclassA{abstractvoidmyMethod();}classB:A{voidmyMethod(){}}

classA{virtualvoidmyMethod();}classB:A{overridevoidmyMethod(){}}

解决方案三:
请问楼主具体要实现什么呢说个例子看看
解决方案四:
目的就是:Ac=newB();在c中,希望能得到h,g,我用了强制转换,casB,结果c中的成员全都变为空,显然这样是不成功的。
解决方案五:
classA{publicvirtualintGetH();publicvirtualintGetG();}classB:A{privateinth,g;publicB(){h=1;g=2;}publicoverridevoidGetH(){returnh;}publicoverridevoidGetG(){returng;}}

这样可以通过基类的两个函数获取hg了
解决方案六:
1、对接口编程"对接口编程"是面向对象设计(OOD)的第一个基本原则。它的含义是:使用接口和同类型的组件通讯,即,对于所有完成相同功能的组件,应该抽象出一个接口,它们都实现该接口。具体到JAVA中,可以是接口(interface),或者是抽象类(abstractclass),所有完成相同功能的组件都实现该接口,或者从该抽象类继承。我们的客户代码只应该和该接口通讯,这样,当我们需要用其它组件完成任务时,只需要替换该接口的实现,而我们代码的其它部分不需要改变!当现有的组件不能满足要求时,我们可以创建新的组件,实现该接口,或者,直接对现有的组件进行扩展,由子类去完成扩展的功能。2、优先使用对象组合,而不是类继承"优先使用对象组合,而不是类继承"是面向对象设计的第二个原则。并不是说继承不重要,而是因为每个学习OOP的人都知道OO的基本特性之一就是继承,以至于继承已经被滥用了,而对象组合技术往往被忽视了。下面分析继承和组合的优缺点:类继承允许你根据其他类的实现来定义一个类的实现。这种通过生成子类的复用通常被称为白箱复用(white-boxreuse)。术语"白箱"是相对可视性而言:在继承方式中,父类的内部细节对子类可见。对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组合对象来获得。对象组合要求对象具有良好定义的接口。这种复用风格被称为黑箱复用(black-boxreuse),因为被组合的对象的内部细节是不可见的。对象只以"黑箱"的形式出现。继承和组合各有优缺点。类继承是在编译时刻静态定义的,且可直接使用,类继承可以较方便地改变父类的实现。但是类继承也有一些不足之处。首先,因为继承在编译时刻就定义了,所以无法在运行时刻改变从父类继承的实现。更糟的是,父类通常至少定义了子类的部分行为,父类的任何改变都可能影响子类的行为。如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。对象组合是通过获得对其他对象的引用而在运行时刻动态定义的。由于组合要求对象具有良好定义的接口,而且,对象只能通过接口访问,所以我们并不破坏封装性;只要类型一致,运行时刻还可以用一个对象来替代另一个对象;更进一步,因为对象的实现是基于接口写的,所以实现上存在较少的依赖关系。优先使用对象组合有助于你保持每个类被封装,并且只集中完成单个任务。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物(这正是滥用继承的后果)。另一方面,基于对象组合的设计会有更多的对象(但只有较少的类),且系统的行为将依赖于对象间的关系而不是被定义在某个类中。注意:理想情况下,我们不用为获得复用而去创建新的组件,只需要使用对象组合技术,通过组装已有的组件就能获得需要的功能。但是事实很少如此,因为可用的组件集合并不丰富。使用继承的复用使得创建新的组件要比组装已有的组件来得容易。这样,继承和对象组合常一起使用。然而,正如前面所说,千万不要滥用继承而忽视了对象组合技术。相关的设计模式有:Bridge、Composite、Decorator、Observer、Strategy等。下面的例子演示了这个规则,它的前提是:我们对同一个数据结构,需要以任意的格式输出。第一个例子,我们使用基于继承的框架,可以看到,它很难维护和扩展。abstractclassAbstractExampleDocument{//skipsomecode...publicvoidoutput(Examplestructure){if(null!=structure){this.format(structure);}}protectedvoidformat(Examplestructure);}第二个例子,我们使用基于对象组合技术的框架,每个对象的任务都清楚的分离开来,我们可以替换、扩展格式类,而不用考虑其它的任何事情。classDefaultExampleDocument{//skipsomecode...publicvoidoutput(Examplestructure){ExampleFormatterformatter=(ExampleFormatter)manager.lookup(Roles.FORMATTER);if(null!=structure){formatter.format(structure);}}}这里,用到了类似于"抽象工厂"的组件创建模式,它将组件的创建过程交给manager来完成;ExampleFormatter是所有格式的抽象父类;3、将可变的部分和不可变的部分分离"将可变的部分和不可变的部分分离"是面向对象设计的第三个原则。如果使用继承的复用技术,我们可以在抽象基类中定义好不可变的部分,而由其子类去具体实现可变的部分,不可变的部分不需要重复定义,而且便于维护。如果使用对象组合的复用技术,我们可以定义好不可变的部分,而可变的部分可以由不同的组件实现,根据需要,在运行时动态配置。这样,我们就有更多的时间关注可变的部分。对于对象组合技术而言,每个组件只完成相对较小的功能,相互之间耦合比较松散,复用率较高,通过组合,就能获得新的功能。4、减少方法的长度通常,我们的方法应该只有尽量少的几行,太长的方法会难以理解,而且,如果方法太长,则应该重新设计。对此,可以总结为以下原则:三十秒原则:如果另一个程序员无法在三十秒之内了解你的函数做了什么(What),如何做(How)以及为什么要这样做(Why),那就说明你的代码是难以维护的,必须得到提高;一屏原则:如果一个函数的代码长度超过一个屏幕,那么或许这个函数太长了,应该拆分成更小的子函数;一行代码尽量简短,并且保证一行代码只做一件事那种看似技巧性的冗长代码只会增加代码维护的难度。5、消除case/if语句要尽量避免在代码中出现判断语句,来测试一个对象是否某个特定类的实例。通常,如果你需要这么做,那么,重新设计可能会有所帮助。我在工作中遇到这样的一个问题:我们在使用JAVA做XML解析时,对每个标签映射了一个JAVA类,采用SAX(简单的XML接口API:SimpleAPIforXML)模型。结果,代码中反复出现了大量的判断语句,来测试当前的标签类型。为此,我们重新设计了DTD(文档类型定义:DocumentTypeDefinition),为每个标签增加了一个固定的属性:classname,而且重新设计了每个标签映射的JAVA类的接口,统一了每个对象的操作:addElement(ElementaElement);//增加子元素addAttribute(StringattName,Stringattvalue);//增加属性;则彻底消除了所有的测试当前的标签类型的判断语句。每个对象通过Class.forName(aElement.attributes.getAttribute("classname")).newInstence();动态创建,6、减少参数个数有大量参数需要传递的方法,通常很难阅读。我们可以将所有参数封装到一个对象中来完成对象的传递,这也有利于错误跟踪。许多程序员因为,太多层的对象包装对系统效率有影响。是的,但是,和它带来的好处相比,我们宁愿做包装。毕竟,"封装"也是OO的基本特性之一,而且,"每个对象完成尽量少(而且简单)的功能",也是OO的一个基本原则。7、类层次的最高层应该是抽象类在许多情况下,提供一个抽象基类有利做特性化扩展。由于在抽象基类中,大部分的功能和行为已经定义好,使我们更容易理解接口设计者的意图是什么。由于JAVA不允许"多继承",从一个抽象基类继承,就无法再从其它基类继承了。所以,提供一个抽象接口(interface)是个好主意,一个类可以实现多个接口,从而模拟实现了"多继承",为类的设计提供了更大的灵活性。8、尽量减少对变量的直接访问对数据的封装原则应该规范化,不要把一个类的属性暴露给其它类,而是应该通过访问方法去保护他们,这有利于避免产生波纹效应。如果某个属性的名字改变,你只需要修改它的访问方法,而不是修改所有相关的代码。9、子类应该特性化,完成特殊功能如果一个子类只是使一个组件变成组件管理器,而不是实现接口功能,或者,重载某个功能,那么,就应该使用一个外部的容器类,而不是创建一个子类。建议:类层次结构图,不要太深;例如:下面的接口定义了组件的功能:发送消息;类Transceiver实现了该接口;而其子类Pool只是管理多个Transceiver对象,而没有提供自己的接口实现。建议使用组合方式,而不是继承!publicinterfaceITransceiver{publicabstractsend(Stringmsg);}publicclassTransceiverimplementsITransceiver{publicsend(Stringmsg){System.out.println(msg);}}//使用继承方式的实现publicclassPoolextendsTransceiver{privateListpool=newVector();publicvoidadd(TransceiveraTransceiver){pool.add(aTransceiver);}publicTransceiverget(intindex){pool.get(index);}}//使用组合方式的实现publicclassPool{privateListpool=newVector();publicvoidadd(TransceiveraTransceiver){pool.add(aTransceiver);}publicTransceiverget(intindex){pool.get(index);}}10、拆分过大的类如果一个类有太多的方法(超过50个),那么它可能要做的工作太多,我们应该试着将它的功能拆分到不同的类中,类似于规则四。11、作用截然不同的对象应该拆分在构建的过程中,你有时会遇到这样的问题:对同样的数据,有不同的视图。某些属性描述的是数据结构怎样生成,而某些属性描述的是数据结构本身。最好将这两个视图拆分到不同的类中,从类名上就可以区分出不同视图的作用。类的域、方法也应该有同样的考虑!12、尽量减少对参数的隐含传递两个方法处理类内部同一个数据(域),并不意味着它们就是对该数据(域)做处理。许多时候,该数据(域)应该作为方法的参输入数,而不是直接存取,在工具类的设计中尤其应该注意。例如:publicclassTest{privateListpool=newVector();publicvoidtestAdd(Stringstr){pool.add(str);}publicObjecttestGet(intindex){pool.get(index);}}两个方法都对List对象pool做了操作,但是,实际上,我们可能只是想对List接口的不同实现Vector、ArrayList等做存取测试。所以,代码应该这样写:publicclassTest{privateListpool=newVector();publicvoidtestAdd(Listpool,Stringstr){pool.add(str);}publicObjecttestGet(Listpool,intindex){pool.get(index);}
解决方案七:
这不符合继承的思想吧。继承应该是新类可以共享父类的操作和数据,而不是反过来
解决方案八:
你的Ac=newB();c的地址就是对B的一个引用c实际就是指向B的不过因为是继承,你通过“调试”F11一步步的调试是可以discover到b中再到A中去找到匹配的constructor完后再到应用程序入口的方法继续执行好好调试你会有收获

时间: 2024-10-25 12:26:18

请教问题父类访问子类问题的相关文章

C# 父类访问子类的静态变量或方法

问题描述 问题:A父类,B子类classA{publicstaticinti;int_j;pubicabstractintj{get;}}classB:A{publicstaticinti;pubicoverrideintj{get{return_j;}}}我想通过父类A直接访问到B类中的静态变量i,如何才能做到?类似对于非静态内容,如Aa=newB();a.j;就可访问到方法j.对于静态内容,如何处理?哪位大神知道? 解决方案 解决方案二:A.i解决方案三:引用1楼hanjun0612的回复:

wpf c#-请教:WPF中 子类继承父类的INotifyPropertyChanged的问题

问题描述 请教:WPF中 子类继承父类的INotifyPropertyChanged的问题 父类实现了INotifyPropertyChanged接口,子类数据改变时如何驱动父类的INotifyPropertyChanged? 父类实现接口方法: public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// 数据驱动 /// </summary> /// <param name=&quo

c++-C++ 父类变量保存子类对象 怎样访问子类对象的属性

问题描述 C++ 父类变量保存子类对象 怎样访问子类对象的属性 class Command { public: int id; int type; } class OnCommand : Command { public: int OnCount; } 先申明了一个父类的变量 Command cmd; 经过一些处理后 cmd被赋值了一个OnCommand对象 请问如何将cmd转换为OnCommand然后获取里边OnCount属性的值? 不允许这样获取么? 解决方案 你所用的是继承,而不是内嵌对象

C#基础知识—父类和子类的关系

基础知识一: using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace WindowsFormsApplication2 { public class ParentClass { public ParentClass() { } public string NamePropety { get; set; } public string GetNa

java中父类与子类, 不同的两个类中的因为构造函数由于递归调用导致栈溢出问题

/* 对于类中对成员变量的初始化和代码块中的代码全部都挪到了构造函数中, 并且是按照java源文件的初始化顺序依次对成员变量进行初始化的,而原构造函数中的代码则移到了构造函数的最后执行 */ import static java.lang.System.out; public class PersonDemo { public static void main(String[] args) { //*********测试父类与子类之间的循环调用的问题 out.println("main1&quo

PHP父类调用子类方法的代码例子

 这篇文章主要介绍了PHP父类调用子类方法的代码例子,需要的朋友可以参考下 今天突然发现需要在父类中调用子类的方法,之前一直都没这么用过,通过实践发现也可以.例子如:  代码如下: <?php /**  * 父类调用子类方法 基类  * @author LNMP100  *  */ class BaseApp {     /**      * 调用子类方法      * @version  创建时间:2013-07-10      */     function _run_action()  

java+ 程序 子类继承父类 创建子类对象时构造方法中无显示调用父类构造方法

问题描述 java+ 程序 子类继承父类 创建子类对象时构造方法中无显示调用父类构造方法 创建子类对象时,Student s = new Student(""school""); 该构造方法中没有显示调用父类的构造方法,但还是编译成功了,该构造方法调用自身的构造函数,此构造函数中有调用父类的构造方法,执行成功的原因是什么 解决方案 不用显示调用,会自动执行父类的构造 解决方案二: 子类的构造方法中,如果没有显示调用父类的构造方法,会默认调用父类无参的构造方法.类似于

java中除了父类,子类可以有同名的方法

问题描述 java中除了父类,子类可以有同名的方法 java中除了父类,子类可以有同名的方法 非子类,父类,可以有同名的方法吗 b是a的父类,b是c的父类,那a是c的父类吗 解决方案 b是a的父类,b是c的父类,那a是c的父类吗 显然不是,a和c是"兄弟",或者说无关 非子类,父类,可以有同名的方法吗 可以. 解决方案二: 应该说是吧? C和A不是直接继承,在用的时候自然就不能直接用, 解决方案三: a和c没有继承关系,当然可以有同名的方法

java中方法的重写概念是相对于父类和子类的,那么同一个类到底有没有重写的概念呢

问题描述 java中方法的重写概念是相对于父类和子类的,那么同一个类到底有没有重写的概念呢 java中方法的重写概念是相对于父类和子类的,那么同一个类到底有没有重写的概念呢 解决方案 重写是在有继承关系的多个类之间,子类有与父类相同声明的方法但是方法体不同,即子类重写了父类的某些方法. 所以同一个类中显然是没有重写的概念的. 解决方案二: 没有,重写是在有继承关系的两个类中发生的. 解决方案三: 同一个类中只有重载,继承关系之间的类叫重写 解决方案四: 没有的,本类只有重载方法. 解决方案五: