“关于克隆”
好吧,由于一个大错误,您将无法理解:B 类是 A 扩展类。首先意味着有一个a类,仅此而已。
也许想象它是你自己的克隆,但没有太多指示下一步该做什么,但它已经可以像你一样走路和睡觉,但它不会说话,不知道如何吃饭或弹钢琴。所以这个可怜的家伙不会为自己存在很长时间,但你已经知道你在做什么:你所要做的就是克隆克隆并让下一个比第一个更好。第二个可以吃,喝和许多其他有趣的事情,但它不会说话。所以你创造了一个、两个和三个其他的。一个人可以和你的朋友交谈,并且很高兴在没有被喂食的情况下过上它的生活。接下来是做你所有的工作,最后一个会关灯。
让我们想想开始:你做了一个愚蠢的克隆,但它有两个特征——走路和睡觉。因为它是先锋状态,你可以称他为克隆A,甚至更好地称为A级克隆。
在您的下一次克隆操作中,您构建了成功的 B 类克隆。这个主要通过两个新优势扩展了 A 类克隆:吃和喝。为了能够做到这一点,您还将在哪里可以找到冰箱和酒吧的信息添加到 B 类克隆的寻路系统中。由于这个原因,您必须覆盖 A 类克隆的行走 dna。这怎么可能?
第一个克隆:
class CloneA
{
void walk()
{
Position p = getRandomPosition();
walkTo( p );
};
void sleep()
{
sleepy = sleepy - 1;
}
void main()
{
if ( itIsLate() )
sleep();
else
walk();
}
}
它的主程序控制克隆何时休眠或何时四处走动。它使用了三种已知的方法:getRandomPosition()、walkTo(Position) 和 itIsLate()。你在旧手机上找到了这个实用的东西,然后把它交给了克隆,随着时间的推移,它必须做更多有意义的事情。例如,让我们看一下 B 类克隆。CloneB主要获得了另外两个能力:
void drink();
void eat();
正如您之前计划的那样,您不需要创建一个完整的新克隆,您已经有了一个完美的父母。这个继承了它的所有知识给新的。剩下的就是修改步行方法。否则它不会找到现在可以处理的物品的位置。
所以第二个的结构看起来是这样的:
class CloneB extends CloneA
{
void drink() { thursty = thursty - 1; }
void eat() { hungry = hungry - 1; }
@Override
void walk()
{
if ( itIsEary() || itIsLate() )
{
Position fp = fridgePosition;
walkTo( fp );
eat();
Position bp = barPosition;
walkTo( bp );
drink();
}
else
super.walk();
}
}
CloneB 现在检查时间,每次它正在寻找一个新的位置去。如果它识别出迟到或(||)早它会记住冰箱和酒吧的位置并开始一个接一个地走到那里,吃东西,喝东西,当时间到时它会调用walk() super.walk() 对其父 CloneA 的指令;这对你有好处,你不需要两次给出相同的命令。
当您查看这两种生物时,您会发现一些差异,但它们的大部分特征是相同的。也许您已经想到 CloneB 确实是 CloneA。任何使 CloneA 变为 CloneA 的标识符也由 CloneB 继承。更重要的是 - CloneB 可以照顾自己!可悲的是,CloneA 不可能永远是 CloneB。
如果您现在对它们都进行以下简单测试,您应该了解面向对象语言的主要规则之一:
- 把你的两个克隆人都放在一个只有一扇门的小房间里。
- 在一张纸上写下 CloneA 的名字,然后贴在门上。
- 告诉你的克隆人,只有这些克隆人才能进入天堂之门,名字是写在纸上的。
- 让自己进入天堂并重试几次实验。片刻之后,您可以确定:您看到 CloneA 或 CloneB 的机会为 50%。两者对未知对象的查找方法相同,而且都感觉像 CloneA,所以它是纯随机的。你现在也处于另一个劣势;两个克隆看起来相同,此时您唯一知道的是,输入的必须具有 CloneA 的属性。
- 第二天再来,把CloneB的名字写在贴在门口的纸上。你说对了。如果 CloneA 是诚实的克隆,它永远不会通过大门。你可以确定。这是一个克隆 B。
在 Java 中是完全一样的。您的克隆实例,让我们以相同的方式命名这些 cA 和 cB:
CloneA cA = new CloneA();
CloneB cB = new CloneB();
// assign cloneB instance to cloneA instance:
cA = cB;
// error by default:
cB = cA;
如您编写的示例所示,您还可以执行以下操作(天堂方法):
CloneA cA = new CloneB();
缺点:此时 cA 确实是 CloneB,但如果你想给 CloneB 特定的指令,这要么是不可能的,要么是不安全的。谁知道你度假时它是否还活着?
但那时你并不无助。你可以向克隆询问它的继承。同样在这里,他们可能无法告诉您或只是提供了错误的信息。知道他们可能是什么然后问他们是否是你要求他们的人通常是有利的。之后,您可以确定并与您的 CloneA 实例对话,因为它是 CloneB。例如:
CloneA cA = new CloneB();
if ( cA instanceof CloneB )
( CloneB ) cA.eat();
如果您不想再与他们互动,请不要在意。cA 的实例已被新的 CloneB 信息覆盖,如果您知道他的确切身份,则可以独立吃喝。您在上一个代码片段中所做的事情称为类型转换。另一种常用的方法是:
CloneB.class.cast( cA ).eat();
// or storing in a new variable for an easier later handling
CloneB cB = CloneB.class.cast( cA );
现在我们几乎忘记了最后三个实际克隆。但是每个克隆都只有一种扩展方法。你如何计划你的克隆文明不在我的范围内,Java 主要提供了一组丰富的替代方法来做同样的事情。为简单起见,假设您决定克隆 CloneB 三次。这三个克隆的任务差异太大,无法组合。在他们的第一个生日时,您会给他们一份历史礼物——他们的第一棵家谱:
TalkerClone
/
CloneA - CloneB - WorkerClone
\
LightSwitchClone
所以现在开始教他们:你们每个人都是无与伦比的,但你们都是克隆B和(大)克隆A的一部分……
最后我不应该忘记你的问题。也许您现在可以自己回答,但为了完整性:
class A {
public int data=5; // 13.
private int pd = 6;
public void print() { // 6.
System.out.println(data+pd); // 7. ( output "11" )
f(); // 8.
}
protected void f() {
System.out.println(“A::f()”);
}
}
class B extends A { // 2.
public int data=2;
private int pd = 3;
public void print() { // 4.
super.print(); // 5.
System.out.println(data+pd); // 11. ( output 5 )
}
protected void f() { // 9.
System.out.println(“B::f()”); // 10. ( output "B::f()" )
}
}
public class TestAB {
public static void main(String[] args) {
A a = new B(); // Command A; 1.
a.print(); // Command B; 3.
System.out.println(a.data); // Command C; 12. ( output 5, 2nd )
}
}
如果您不确定命令 C, 12th 来自何处,请再次进行天堂实验。
我建议您告知自己有关修改器(公共、受保护等)的信息,以使继承对您的应用程序更有用。
祝你好运,与你的克隆有很多乐趣:)