我是编程新手,对课程有一些疑问。
我将以卡雷尔为例:
public class Karel extends robot{
....
}
然后我延伸了Karel:
public class SuperKarel extends Karel{
....
}
但后来我想组织一些方法组:
public class KarelJumps extends SuperKarel {
....
}
public class KarelColor extends SuperKarel {
....
}
但是如果我想让Karel跳,我必须创建一个实例
KarelJumps
而不是SuperKarel
。但因为KarelJumps
是一个
不同的对象然后KarelColor
我不能使用它的任何方法。
所以我只需要放置所有KarelJumps
和KarelColor
方法
在SuperKarel?
里面我只制作一个大型物体吗?
答案 0 :(得分:4)
扩展类的最有用的原因是,您可以在新对象中使用基础类的功能,然后添加新类型特有的行为和特征。如果没有令人信服的理由这样做,并且经常没有,那么就不要这样做。不要过度复杂化您的设计,只是为了尝试利用多态和继承。
您希望使用这些技术使您的应用程序不那么复杂。对于一个新的程序员,我建议你得到“代码完整”一书,并将它作为你的圣经一段时间。你不会从中学到一门语言,但你将学习如何完成任务以及为什么要这样做。
答案 1 :(得分:2)
看起来你试图理解多态性而不是类。
继承不提供“方法分组”的机制。
经典继承和多态的核心概念可以方便地在Liskov Substitution Principle中捕获。从该维基页面被盗:
如果S是T的子类型,则程序中类型T的对象可以用类型S的对象替换,而不改变该程序的任何所需属性。
确保您的子类可以替代超类,并且除了添加一些重要的适当功能外,否则不要使用继承。
答案 2 :(得分:1)
如果您希望跳转Karel
并且可以访问KarelColor
方法,则需要将它们放在一个类中,或者更改层次结构。
KarelJumps
和KarelColor
是兄弟姐妹,无法访问彼此的方法。如果你真的想把它们分开,可能是:
public class SuperKarel extends Karel
public class KarelJumps extends SuperKarel
public class KarelColor extends KarelJumps
编辑:听听ChrisB的回答。如果您没有为每个扩展类添加重要功能,则可能应该避免使用层次结构。
答案 3 :(得分:1)
我认为你忽略了方法的概念。类是可以包含数据和定义方法的结构。为了执行操作,您不需要继续扩展原始类,您可以定义新方法。扩展Karel很好,只要有一个原因你需要在你的SuperKarel中做一些类似但与Karel不同的事情。
public class Karel extends robot{
public void jump(){
...
}
public void setColor(Color c) {
...
}
}
public class SuperKarel extends Karel{
public void jump(){
//jump in a super way
}
public void setColor(Color c) {
//set some super color
}
}
答案 4 :(得分:0)
每当你创建一个课时,问“它做了什么?”这些方法都在课堂上。
您需要首先从使用您的Karel的人的角度来看。
Here is myK he is a Karel
oh, I wonder what he can do ... hmmm looks like a Karel can jump
myK.jump(howHigh)
hey he jumped
wonder what else he can do ...
那个人不想要的是过多的不同对象myK,mySuperK,myColouredK做不同的工作。你给了他一个很好的连贯的和完整的 Karel对象。
如果您觉得这会导致一个非常大的“Karel”课程,并且您想进一步组织,那么您可以分解Karel实现(想想轮子,笔等)来完成各种任务,但是从外面它是一个Karel
答案 5 :(得分:0)
有几种解决方案:
您可以在课程树中向上移动方法(如您所知)。
您可以使用接口声明常用方法。如果KarelJumps
和KarelColor
实现了接口,则某些代码可能会要求“实现此接口”。由于两个类都实现(满足)接口,因此代码将起作用。缺点:您必须在每个类中实现接口的方法(代码重复 - >坏)。
Java不支持“mixins”,所以这不是一个选项,只是为了完整性:Mixins是编译器为您复制的代码片段。因此,您可以在一个地方维护代码,然后让编译器将所述代码复制到数千个地方(或使用任何其他技巧使其看起来像这样)。
您可以使用委托。然后委托实现该方法。在两个Karel类中,添加一个字段delegate
并调用委托实现:
interface IDelegate { void method (); }
class Delegate implements IDelegate {
void method () { ... }
}
public class KarelJumps extends SuperKarel implements IDelegate {
IDelegate delegate = new Delegate ();
// Instead of copying the code, delegate the work
void method () { delegate.method (); }
}