Java 对物体投射的质疑
我正在帮助一位一年级的朋友准备Java考试。 老师要求他们创造一种方法,可以把音乐家塑造成诗人 没有人知道怎么做。经过一段时间的思考,我得出了这样的结论:这是不可能的(ClassCastException),因为音乐家和诗人共享一个界面的事实不足以将它们投射到另一个界面上 我认为这只有在它们处于同一继承链中时才有可能 现在我有三个问题:Java 对物体投射的质疑,java,Java,我正在帮助一位一年级的朋友准备Java考试。 老师要求他们创造一种方法,可以把音乐家塑造成诗人 没有人知道怎么做。经过一段时间的思考,我得出了这样的结论:这是不可能的(ClassCastException),因为音乐家和诗人共享一个界面的事实不足以将它们投射到另一个界面上 我认为这只有在它们处于同一继承链中时才有可能 现在我有三个问题: 我说得对吗 如果我是对的,教授希望他们做什么?我真怀疑他会要求这样的事 如果我错了,你能写出能把音乐家变成诗人的代码吗 你说得对 诡计问题 不,至少,没有一个C
ClassCastException
李>
你可以试试:
Musician musician = new Musician();
Artist artist = musician;
Poet poet = (Poet)artist;
当然,这些代码在运行时不会真正起作用。你是对的。鉴于您的继承结构,您不能将
音乐家
转换为诗人
您唯一能做的就是创建一个facade对象,它是诗人
,并将相关的方法调用转发给相关的音乐家
public Musician getMusician(Poet p) {
Artist a = p;
return (Musician)a;
}
是的,这将引发ClassCastException。但是,至少从语言层面来看,这似乎是可以做到的。但是运行时会在运行时阻止它。你是对的,Musitor和Poet是不同的类,它们共享相同的基本实现。您唯一可以可靠地执行的操作是使用您所拥有的类图来播放iArtististMusitor或iArtististPoeter。不,你不能把一个音乐家交给一个诗人。你确定教授没有要求你/你的朋友重新设计课程树吗?只是想提出一些想法。。。您可以使用java.lang.reflect.Proxy类吗 编辑 实际上你不需要我提到的代理。使用我从动态分类中借用的想法,你可以实现将音乐家转变为诗人的目标。基本上你所做的就是 您必须创建一个类来扩展poter,在构造函数中接受音乐家。然后在子类中,您可以覆盖每个诗人的方法,将诗人的方法“映射”到音乐家的方法 我在一个类中编写了所有内容,这不是一种好的编程风格,但这样做更容易;-)
音乐家和诗人能成为一个界面吗?如果是这样的话,就有可能有一个同时实现这两种功能的类,可以从音乐家转换成诗人,反之亦然
public interface Musician {
void sing();
}
public interface Poet {
void read();
}
public class Common implements Musician, Poet {
public void sing() {
//sing
}
public void read() {
//read
}
}
public Musician convert(Poet poet) {
if(poet instancof Musician) {
return (Musician) poet;
else {
throw new IllegalArgumentException("Not a musician");
}
}
public void test() {
Common rapper = new Common();
Musician singer = convert(rapper);
}
是 啊也许这是个骗人的问题:)谢谢你的回答。我可以问你一些别的问题吗(我想没有必要开新票,很简单)。你认为如果没有超类,Poter和Musitor只是实现了那个接口,问题还是一样的吗?@sfrj正确,你只能向上抛出继承链,而不是向上或向下。是的,这两个类是否共享一个共同的超类和/或接口都是一样的。从来没有听说过。这是什么?我知道你做了什么。很有趣,但从设计的角度来看,这可能不是一个很好的方法。非常感谢你的帮助。1+对于很酷的类名
PoetWannabe
:)实际上,我认为这种设计是可以的,因为它是适配器模式的一种示例。“PoetWannabe”是将“音乐家”暴露为“诗人”的适配器。也就是说,我同意你的观点,这可能是一个糟糕的设计,取决于问题的背景,所以我想知道你为什么认为这是一个糟糕的设计?我没有说糟糕,我说的是不好的方法。我只是把这个问题作为一个暂时搁置的问题来考虑。这一年级的学生还没有理解模式。教授们正在教他们一些基本的原理,如多面体、遗传、遗传等等。。。我认为他想让他们做一些类型的铸造,但在设计练习时可能犯了一些错误。谢谢分享你的观点:)哦,是的,我的观点被采纳了!我很抱歉,如果我听起来是防御性的,我不是故意的。我只是想得到人们的意见,这样我就能提高自己;-)事实上,我同意你的观点,对于第一年的Java 101,教授可能会犯错误。也许你的问题的正确答案是“给教授发电子邮件澄清”。是“cast”吗在请求的措辞中实际使用的单词是什么?假设cast是使用的确切单词,它要么是一个技巧问题,要么是一个打字错误。@Costi Ciudatu,这是一个好问题。他只是说这个方法应该叫做musicianToPoet(stringfilename)
,没有提到返回类型,还说音乐家的值应该来自一个非常简单的.txt文件file@awoodlandproff是一个很好的人,一定是打字错误,我不知道他会问这样的问题:)我不这么认为。但如果是的话。您建议使用什么UML结构来允许这种类型的转换?学生们应该如何组织课程(注意音乐家和诗人是不同的东西)。你必须从诗人课程中概括出音乐家课程(即移动一个箭头)。让所有的音乐家都是诗人。(尽管你会有很多争论)。然而,当你完成后,你将不需要类型转换。我不确定。音乐家和诗人都有属性,这在接口中是不允许的。你能更新你的帖子,并就我如何改进这个例子提出一些建议吗?我不明白你的建议。我看到了你的更新。是的,我现在明白了。这可能是一个简单的解决方案。也许这样的东西是允许的,但唯一的问题是音乐家和诗人的独特属性必须在同一个类中结合在一起。谢谢,这很有帮助。最后,我认为这是一个“技巧问题”,以确保您了解Java没有多重继承。酷,这是一个非常好的技巧。谢谢你根本不投,但你设法改变了音乐家我
public interface Musician {
void sing();
}
public interface Poet {
void read();
}
public class Common implements Musician, Poet {
public void sing() {
//sing
}
public void read() {
//read
}
}
public Musician convert(Poet poet) {
if(poet instancof Musician) {
return (Musician) poet;
else {
throw new IllegalArgumentException("Not a musician");
}
}
public void test() {
Common rapper = new Common();
Musician singer = convert(rapper);
}
static Poet musicianToPoet(String fileName) {
Poet p = new Poet();
p.readArtist(fileName); // this method is defined in the interface
return p;
}
static Poet musicianToPoet(Musician musician) {
String filename = "/some/file/name.txt";
musician.saveArtist(filename);
return musicianToPoet(filename);
}