ความแตกต่างระหว่างการชี้ขาดขึ้นและลงการชี้ขาดเกี่ยวกับตัวแปรคลาสคืออะไร


138

อะไรคือความแตกต่างระหว่าง up-casting และ down-casting เกี่ยวกับตัวแปร class?

ตัวอย่างเช่นในคลาสโปรแกรมต่อไปนี้ Animal มีเพียงวิธีเดียว แต่คลาส Dog มีสองวิธีจากนั้นเราจะแปลงตัวแปร Dog เป็น Animal Variable ได้อย่างไร

หากการคัดเลือกนักแสดงเสร็จสิ้นแล้วเราจะเรียกสุนัขอีกวิธีหนึ่งด้วยตัวแปรของสัตว์ได้อย่างไร

class Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Animal");
    }
}


class Dog extends Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Dog");
    }

    public void callme2()
    {
        System.out.println("In callme2 of Dog");
    }
}

public class UseAnimlas 
{
    public static void main (String [] args) 
    {
        Dog d = new Dog();      
        Animal a = (Animal)d;
        d.callme();
        a.callme();
        ((Dog) a).callme2();
    }
}

เป็นDog Animalเวลาในการถ่ายทอดข้อมูลส่วนใหญ่นั้นไม่จำเป็นเว้นแต่ว่าคุณต้องการใช้วิธีการโอเวอร์โหลดที่แน่นอน callmeที่มีอยู่ทั้งในและAnimal มีอยู่เฉพาะในที่คุณนำมาใช้เพื่อให้ทำงานได้ Dogcallme2DogaDog
Brian

ผลลัพธ์ของโค้ดของคุณคืออะไร?
Malwinder Singh

สิ่งที่น่าสนใจคือ d.callme ส่งคืน 'In callme of Dog' แม้ว่า d จะถูกร่ายไปยังสัตว์ !!
Chris311

4
@ Chris311 ทั้ง 'd' และ 'a' ชี้ไปที่วัตถุเดียวกัน ... ซึ่งเป็นสุนัข แต่ 'a' มีการเข้าถึงวิธีการเฉพาะของ Dog เมื่อมีการดาวน์สตรีมที่รันไทม์ Infact: สัตว์ a = (สัตว์) d; ไม่จำเป็นคุณต้องใช้สัตว์ a = d; ในขณะที่คุณกำลังอัปโหลด
Mark Keen

คำตอบ:


223

การ upcasting กำลังส่งไปยัง supertype ขณะที่ downcasting กำลังส่งไปยัง subtype อนุญาตให้อัปโหลดได้เสมอ แต่การดาวน์สตรีมเกี่ยวข้องกับการตรวจสอบประเภทและสามารถโยนClassCastExceptionได้

ในกรณีของคุณโยนจากDogไปสู่การAnimalเป็น upCast เพราะเป็น-ADog Animalโดยทั่วไปคุณสามารถ upcast เมื่อใดก็ตามที่มีความสัมพันธ์แบบ is-a ระหว่างสองคลาส

Downcasting จะเป็นดังนี้:

Animal animal = new Dog();
Dog castedDog = (Dog) animal;

โดยทั่วไปสิ่งที่คุณทำจะบอกคอมไพเลอร์ที่คุณรู้ว่าสิ่งที่ประเภทรันไทม์ของวัตถุที่มันเป็น คอมไพเลอร์จะอนุญาตการแปลง แต่จะยังคงแทรกการตรวจสอบสติรันไทม์เพื่อให้แน่ใจว่าการแปลงเหมาะสม ในกรณีนี้หล่อเป็นไปได้เพราะที่รันไทม์animalเป็นจริงDogแม้ว่าประเภทคงที่ของมีanimalAnimal

อย่างไรก็ตามหากคุณต้องทำสิ่งนี้:

Animal animal = new Animal();
Dog notADog = (Dog) animal;

ClassCastExceptionคุณจะได้รับ เหตุผลก็คือว่าทำไมเพราะanimal's ประเภท runtime คือAnimalและอื่น ๆ เมื่อคุณบอกรันไทม์เพื่อดำเนินการโยนมันเห็นว่าanimalไม่ได้จริงๆและเพื่อพ่นDogClassCastException

ในการเรียกใช้เมธอดของซูsuper.method()เปอร์คลาสคุณสามารถทำได้หรือโดยการทำอัพแคสต์

ในการเรียกใช้เมธอดของคลาสย่อยคุณต้องทำ downcast ดังที่แสดงไว้ข้างต้นคุณมักจะเสี่ยงต่อการClassCastExceptionทำสิ่งนี้; อย่างไรก็ตามคุณสามารถใช้instanceofโอเปอเรเตอร์เพื่อตรวจสอบประเภทรันไทม์ของวัตถุก่อนที่จะทำการร่ายซึ่งทำให้คุณสามารถป้องกันClassCastExceptions:

Animal animal = getAnimal(); // Maybe a Dog? Maybe a Cat? Maybe an Animal?
if (animal instanceof Dog) {
    // Guaranteed to succeed, barring classloader shenanigans
    Dog castedDog = (Dog) animal;
}

การดาวน์สตรีมที่เหมาะสมช่วยให้มั่นใจได้ClassCastExceptionหรือไม่ เหมือนในกรณีแรกหรือไม่
Malwinder Singh

@MS คุณหมายถึงอะไร "เหมาะสม"
awksp

2
@awksp นี่คือคำตอบที่ยอดเยี่ยมและชัดเจน ผลรวมทุกอย่างที่ฉันต้องรู้เกี่ยวกับการคัดเลือกนักแสดง
Gautham Honnavara

แน่นอนคุณยังไม่ได้สร้างคลาสที่สัตว์เป็นตัวอย่างของสุนัขใช่ไหม แล้วทำไมคุณถึงตรวจสอบมัน?
barlop

62

Down-casting และ up-casting เป็นดังนี้:
ป้อนคำอธิบายรูปภาพที่นี่

Upcasting : เมื่อเราต้องการส่งคลาสย่อยไปยังคลาส Super เราใช้ Upcasting มันเกิดขึ้นโดยอัตโนมัติไม่จำเป็นต้องทำอะไรอย่างชัดเจน

Downcasting : เมื่อเราต้องการที่จะส่ง Super class ไปยัง Sub class เราใช้ Downcasting (หรือการ จำกัด ) และการ Downcasting นั้นไม่สามารถทำได้โดยตรงใน Java เราต้องทำอย่างชัดเจน

Dog d = new Dog();
Animal a = (Animal) d; //Explicitly you have done upcasting. Actually no need, we can directly type cast like Animal a = d; compiler now treat Dog as Animal but still it is Dog even after upcasting
d.callme();
a.callme(); // It calls Dog's method even though we use Animal reference.
((Dog) a).callme2(); // Downcasting: Compiler does know Animal it is, In order to use Dog methods, we have to do typecast explicitly.
// Internally if it is not a Dog object it throws ClassCastException

ดังนั้นจึงไม่มีวิธีใดในการทำการ upcasting เพื่อเรียก parent ของเมธอด?
karlihnos

32

การ upcasting และ downcasting เป็นส่วนสำคัญของ Java ซึ่งช่วยให้เราสามารถสร้างโปรแกรมที่ซับซ้อนโดยใช้ไวยากรณ์ง่าย ๆ และให้ประโยชน์ที่ยอดเยี่ยมแก่เราเช่น Polymorphism หรือการจัดกลุ่มวัตถุต่าง ๆ Java อนุญาตให้วัตถุประเภท subclass จะถือว่าเป็นวัตถุประเภท superclass ใด ๆ สิ่งนี้เรียกว่าการถ่ายทอดสด การอัพแคสต์จะกระทำโดยอัตโนมัติในขณะที่นักดาวน์ไลท์จะต้องทำเองโดยโปรแกรมเมอร์และฉันจะอธิบายให้ดีที่สุดว่าทำไมมันถึงเป็นเช่นนั้น

การ upcasting และ downcasting นั้นไม่เหมือนกับการทำการแคสติ้งแบบดั้งเดิมจากที่หนึ่งไปยังอีกที่หนึ่งและฉันเชื่อว่านั่นเป็นสิ่งที่ทำให้เกิดความสับสนมากเมื่อโปรแกรมเมอร์เริ่มเรียนรู้การคัดเลือกวัตถุ

ความหลากหลาย: วิธีการทั้งหมดใน java เป็นเสมือนโดยค่าเริ่มต้น นั่นหมายความว่าวิธีการใด ๆ สามารถแทนที่เมื่อนำมาใช้ในการรับมรดกเว้นแต่วิธีการที่ถูกประกาศเป็นครั้งสุดท้ายหรือคง

คุณสามารถดูตัวอย่างด้านล่างวิธีการgetType();ทำงานตามประเภทของวัตถุ (สุนัขสัตว์เลี้ยงสุนัขตำรวจ)

สมมติว่าคุณมีสุนัขสามตัว

  1. Dog - นี่คือ Super Class

  2. สัตว์เลี้ยงสุนัข - สุนัขสัตว์เลี้ยงขยายสุนัข

  3. Police Dog - Dog Police ขยาย Dog Pet

    public class Dog{ 
       public String getType () {
          System.out.println("NormalDog");
          return "NormalDog";
       }
     }
    
    /**
     * Pet Dog has an extra method dogName()
     */   
    public class PetDog extends Dog{ 
       public String getType () {
          System.out.println("PetDog");
          return "PetDog";
       }
       public String dogName () {
          System.out.println("I don't have Name !!");
          return "NO Name";
       }
     }
    
    /**
     * Police Dog has an extra method secretId()
     */
    public class PoliceDog extends PetDog{
    
     public String secretId() {
        System.out.println("ID");
        return "ID";
     }
    
     public String getType () {
         System.out.println("I am a Police Dog");
         return "Police Dog";
     }
    }

ความหลากหลาย: วิธีการทั้งหมดใน java เป็นเสมือนโดยค่าเริ่มต้น ซึ่งหมายความว่าวิธีการใด ๆ สามารถแทนที่ได้เมื่อใช้ในการสืบทอดเว้นแต่ว่าวิธีการนั้นจะถูกประกาศเป็นขั้นสุดท้ายหรือคงที่ (คำอธิบายเป็นแนวคิดของตารางเสมือนจริง)

ตารางเสมือน / ตารางส่งข้อมูล: ตารางส่งของวัตถุจะมีที่อยู่ของวิธีการผูกแบบไดนามิกของวัตถุ การเรียกเมธอดจะดำเนินการโดยดึงที่อยู่ของเมธอดจากตารางการจัดส่งของวัตถุ ตารางการจัดส่งจะเหมือนกันสำหรับวัตถุทั้งหมดที่อยู่ในระดับเดียวกันและโดยทั่วไปจะใช้ร่วมกันระหว่างพวกเขา

public static void main (String[] args) {
      /**
       * Creating the different objects with super class Reference
       */
     Dog obj1 = new Dog();
`         /**
           *  Object of Pet Dog is created with Dog Reference since                
           *  Upcasting is done automatically for us we don't have to worry about it 
           *  
           */
     Dog obj2 = new PetDog();
`         /**
           *  Object of Police Dog is created with Dog Reference since                
           *  Upcasting is done automatically for us we don't have to worry       
           *  about it here even though we are extending PoliceDog with PetDog 
           *  since PetDog is extending Dog Java automatically upcast for us 
           */
      Dog obj3 = new PoliceDog();
}



 obj1.getType();

พิมพ์ Normal Dog

  obj2.getType();

พิมพ์ Pet Dog

 obj3.getType();

พิมพ์ Police Dog

โปรแกรมเมอร์ต้องทำด้วยตนเอง

เมื่อคุณพยายามที่จะเรียกใช้secretID();เมธอดobj3ที่PoliceDog objectอ้างถึงDogซึ่งเป็นคลาสระดับสูงในลำดับชั้นมันจะพ่นข้อผิดพลาดเนื่องจากobj3ไม่มีการเข้าถึงsecretId()เมธอด ในการที่จะเรียกใช้เมธอดนั้นคุณจำเป็นต้อง Downcast ที่ obj3 ด้วยตนเอง PoliceDog

  ( (PoliceDog)obj3).secretID();

ซึ่งพิมพ์ ID

ในทำนองเดียวกันกับเรียกdogName();วิธีการในPetDogระดับที่คุณต้องเศร้าใจobj2ไปPetDogตั้งแต่ obj2 มีการอ้างอิงไปDogและไม่ได้มีการเข้าถึงdogName();วิธีการ

  ( (PetDog)obj2).dogName();

ทำไมเป็นเช่นนั้นการอัพคาสต์จึงเป็นไปโดยอัตโนมัติ แต่การดาวน์สตรีมจะต้องทำด้วยตนเอง คุณจะเห็นว่าการอัปสต์ไม่อาจล้มเหลวได้ แต่ถ้าคุณมีกลุ่มของสุนัขที่แตกต่างกันและต้องการที่จะเศร้าใจพวกเขาทั้งหมดเพื่อประเภทของพวกเขาแล้วมีโอกาสที่บางส่วนของสุนัขเหล่านี้เป็นจริงที่แตกต่างกันเช่น, PetDog, และกระบวนการล้มเหลวโดยการขว้างปาPoliceDogClassCastException

นี่คือเหตุผลที่คุณจำเป็นต้องdowncast วัตถุของคุณด้วยตนเองหากคุณได้อ้างอิงวัตถุของคุณเป็นประเภทซุปเปอร์คลาส

หมายเหตุ: ที่นี่โดยการอ้างอิงหมายความว่าคุณไม่ได้เปลี่ยนที่อยู่หน่วยความจำของ oject ของคุณเมื่อคุณ downcast มันยังคงเหมือนเดิมคุณเพียงแค่จัดกลุ่มให้เป็นประเภทเฉพาะในกรณีนี้ Dog


'ความหลากหลายใช้การดาวน์สตรีมอัตโนมัติระหว่างการเรียกใช้เมธอด' ไม่มันไม่ ไม่ได้ระบุกลไกที่ใช้ แต่กลไกที่ใช้บ่อยที่สุดคือ vtable - ไม่ทำสิ่งนั้น ดูในรหัสวัตถุ ไม่มีการลดทอน
มาร์ควิสแห่ง Lorne

ทำไมจะไม่ล่ะ? นี่คือสิ่งที่เกิดขึ้นถูกต้องคุณสามารถให้ตัวอย่างที่มันจะไม่ทำงาน?
Nagarjuna Yelisetty

1
ทำไมจะไม่ล่ะ? นี่คือสิ่งที่เกิดขึ้น .. คุณช่วยยกตัวอย่างที่คำสั่ง 'Polymorphism ใช้ downcast อัตโนมัติระหว่างการเรียกใช้เมธอด' จะล้มเหลวหรือไม่ถือจริง
Nagarjuna Yelisetty

มันคือการต่อสู้ของคุณ มันขึ้นอยู่กับคุณที่จะพิสูจน์มัน แสดงตำแหน่งที่อยู่ในรหัสวัตถุที่มีการลดลงเกิดขึ้น คำตอบของคำถามที่ว่า "ทำไมไม่" คือ "เพราะไม่จำเป็น" vtable ดูแลวิธีการแจกจ่ายและตัวแปรชี้ไปที่วัตถุทั้งหมดแล้ว
มาร์ควิสแห่ง Lorne

1
'ตามความรู้ของฉันข้อความของฉันเป็นจริงและมันถือในทุกกรณี' ไม่ใช่ข้อพิสูจน์ มันเป็นเพียงการยืนยัน ฉันขอให้คุณพิสูจน์ข้อความของคุณ คุณไม่ทำเช่นนั้น ผลก็คือคุณจะทำซ้ำตัวเองเท่านั้น และฉันได้ให้การรับรองหลายครั้งแล้ว ฉันได้จัดทำขั้นตอนการตัดสินใจด้วย หากคุณพบว่าการดาวน์สตรีมในโค้ดออบเจ็กต์สำหรับการเรียกเมธอดแสดงว่าคุณพูดถูกและผิด นี่คือวิธีที่วิทยาศาสตร์ทำ ทำมัน. และอ้างว่าฉันเป็น 'กล้าหาญขึ้นอยู่กับเอกสาร' เป็นความจริงที่เห็นได้ชัด อย่าทำอย่างนั้น
มาร์ควิสแห่ง Lorne

12

ฉันรู้ว่าคำถามนี้ถามมานานแล้ว แต่สำหรับผู้ใช้ใหม่ของคำถามนี้ โปรดอ่านบทความนี้ที่มีคำอธิบายที่สมบูรณ์เกี่ยวกับการ upcasting, downcasting และการใช้งานอินสแตนซ์ของ โอเปอเรเตอร์

  • ไม่จำเป็นต้อง upcast ด้วยตนเองมันเกิดขึ้นด้วยตัวเอง:

    Mammal m = (Mammal)new Cat(); เท่ากับ Mammal m = new Cat();

  • แต่การดาวน์สตรีมจะต้องทำด้วยตนเองเสมอ:

    Cat c1 = new Cat();      
    Animal a = c1;      //automatic upcasting to Animal
    Cat c2 = (Cat) a;    //manual downcasting back to a Cat

ทำไมเป็นเช่นนั้นการอัพคาสต์จึงเป็นไปโดยอัตโนมัติ แต่การดาวน์สตรีมจะต้องทำด้วยตนเอง คุณจะเห็นว่าการอัปสต์ไม่อาจล้มเหลวได้ แต่ถ้าคุณมีกลุ่มของสัตว์ที่แตกต่างกันและต้องการที่จะลดทอนพวกเขาทั้งหมดให้กับแมวแล้วก็มีโอกาสที่สัตว์เหล่านี้บางตัวเป็นสุนัขจริงและกระบวนการล้มเหลวโดยการขว้าง ClassCastException นี่คือที่ที่ควรแนะนำคุณสมบัติที่มีประโยชน์ที่เรียกว่า"instanceof"ซึ่งจะทดสอบว่าวัตถุนั้นเป็นอินสแตนซ์ของบางคลาสหรือไม่

 Cat c1 = new Cat();         
    Animal a = c1;       //upcasting to Animal
    if(a instanceof Cat){ // testing if the Animal is a Cat
        System.out.println("It's a Cat! Now i can safely downcast it to a Cat, without a fear of failure.");        
        Cat c2 = (Cat)a;
    }

สำหรับข้อมูลเพิ่มเติมโปรดอ่านบทความนี้


จุดที่ดี: เลี้ยงลูกด้วยนม m = (เลี้ยงลูกด้วยนม) แมวใหม่ (); เท่ากับ Mammal m = new Cat ();
Catbuilts

6

ลองวิธีนี้ดีกว่าสำหรับการถ่ายทอดสดมันง่ายที่จะเข้าใจ:

/* upcasting problem */
class Animal
{ 
    public void callme()
    {
        System.out.println("In callme of Animal");
    }
}

class Dog extends Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Dog");
    }

    public void callme2()
    {
        System.out.println("In callme2 of Dog");
    }
}

public class Useanimlas 
{
    public static void main (String [] args) 
    {
        Animal animal = new Animal ();
        Dog dog = new Dog();
        Animal ref;
        ref = animal;
        ref.callme();
        ref = dog;
        ref.callme();
    }
}

และในบรรทัดสุดท้ายอาจเป็น: ((สุนัข) อ้างอิง). callme2 (); // สำหรับการเข้าถึงวิธี downcasting / narrowing และ callme2 () ของคลาส Dog
udarH3

6

บางทีตารางนี้อาจช่วยได้ เรียกcallme()วิธีการของการเรียนหรือระดับParent Childตามหลักการ:

UPCASTING -> การซ่อน

DOWNCASTING -> เปิดเผย

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่


4

1.- upcasting

ทำ upcasting, คุณกำหนดแท็กบางประเภทที่มีการชี้ไปยังวัตถุของชนิดย่อยหนึ่ง (ชนิดและประเภทย่อยอาจจะเรียกว่าชั้นเรียนและ subclass ถ้าคุณรู้สึกสะดวกสบายมากขึ้น ... )

Animal animalCat = new Cat();

อะไรหมายความว่าแท็ก animalCat นั้นจะมีฟังก์ชั่น (วิธีการ) ของประเภทสัตว์เท่านั้นเนื่องจากเราได้ประกาศว่าเป็นประเภทสัตว์ไม่ใช่ประเภทแมว

เราได้รับอนุญาตให้ทำเช่นนั้นในแบบ "ธรรมชาติ / โดยปริยาย / อัตโนมัติ" ที่รวบรวมเวลาหรือในเวลาทำงานส่วนใหญ่เป็นเพราะแมวสืบทอดการทำงานบางอย่างจากสัตว์ ตัวอย่างเช่น move () (อย่างน้อยแมวก็เป็นสัตว์ใช่มั้ย)

2.- Downcasting

แต่จะเกิดอะไรขึ้นถ้าเราต้องการฟังก์ชั่นของ Cat จาก Animal tag ของเรา?

เนื่องจากเราได้สร้างแท็ก AnimalCat ที่ชี้ไปที่วัตถุ Cat เราจำเป็นต้องมีวิธีการเรียกวิธีวัตถุ Cat จากแท็ก AnimalCat ของเราในวิธีที่ชาญฉลาด

ขั้นตอนดังกล่าวเป็นสิ่งที่เราเรียกว่า Downcasting และเราสามารถทำได้ในเวลาทำงานเท่านั้น

เวลาสำหรับรหัสบางส่วน:

public class Animal {
    public String move() {
        return "Going to somewhere";
    }
}

public class Cat extends Animal{
    public String makeNoise() {
        return "Meow!";
    }   
}

public class Test {

    public static void main(String[] args) {
        
    //1.- Upcasting 
    //  __Type_____tag________object
        Animal animalCat = new Cat();
    //Some animal movement
        System.out.println(animalCat.move());
        //prints "Going to somewhere"
        
    //2.- Downcasting   
    //Now you wanna make some Animal noise.
        //First of all: type Animal hasn't any makeNoise() functionality.
        //But Cat can do it!. I wanna be an Animal Cat now!!
        
        //___________________Downcast__tag_____ Cat's method
        String animalNoise = ( (Cat) animalCat ).makeNoise();
        
        System.out.println(animalNoise);
        //Prints "Meow!", as cats usually done.
        
    //3.- An Animal may be a Cat, but a Dog or a Rhinoceros too.
        //All of them have their own noises and own functionalities.
        //Uncomment below and read the error in the console:
        
    //  __Type_____tag________object
        //Cat catAnimal = new Animal();
        
    }

}

2

ผู้ปกครอง: รถ
เด็ก:
รถFigo c1 = ใหม่ Figo ();

=====
Upcasting: -
วิธีการ: Object c1 จะอ้างถึงวิธีการของ Class (Figo - วิธีจะต้องถูกแทนที่) เพราะ class "Figo" ถูกระบุด้วย "new"
ตัวแปรอินสแตนซ์: Object c1 จะอ้างถึงตัวแปรอินสแตนซ์ของ Class Declaration ("Car")

เมื่อคลาส Declaration เป็นพาเรนต์และวัตถุถูกสร้างขึ้นจากเด็กการร่ายโดยปริยายจะเกิดขึ้นซึ่งก็คือ "Upcasting"

======
Downcasting: -
Figo f1 = (Figo) c1; //
วิธีการ: วัตถุ f1 จะอ้างถึงวิธีการเรียน (figo) เป็นวัตถุเริ่มต้น c1 ถูกสร้างขึ้นด้วยระดับ "Figo" แต่เมื่อเสร็จสิ้นการแคสติ้งแล้วเมธอดซึ่งมีอยู่ในคลาส "Figo" เท่านั้นยังสามารถอ้างอิงได้โดยตัวแปร f1
ตัวแปรอินสแตนซ์: Object f1 จะไม่อ้างถึงตัวแปรอินสแตนซ์ของคลาส Declaration ของอ็อบเจกต์ c1 (คลาสการประกาศสำหรับ c1 คือ CAR) แต่ด้วยการแคสต์ลงมันจะอ้างถึงตัวแปรอินสแตนซ์ของคลาส Figo

====== การ
ใช้งาน: เมื่อ Object เป็นคลาส Child และคลาส declaration คือ Parent และ Child class ต้องการเข้าถึงตัวแปรอินสแตนซ์ของคลาสของตัวเองและไม่ใช่คลาสแม่ดังนั้นสามารถทำได้ด้วย "Downcasting"


1

upcasting หมายถึงการคัดเลือกวัตถุไปยัง supertype ในขณะที่ downcasting หมายถึงการคัดเลือกให้เป็นประเภทย่อย

ใน java ไม่จำเป็นต้องทำการ upcasting เพราะมันทำโดยอัตโนมัติ และมันมักจะเรียกว่าการคัดเลือกโดยปริยาย คุณสามารถระบุให้ชัดเจนเพื่อผู้อื่น

ดังนั้นการเขียน

Animal a = (Animal)d;

หรือ

Animal a = d;

นำไปสู่ตรงจุดเดียวกันและในทั้งสองกรณีจะถูกประหารชีวิตจากcallme()Dog

Downcasting นั้นจำเป็นเพราะคุณกำหนดให้aเป็นวัตถุของสัตว์ ตอนนี้คุณรู้แล้วว่ามันเป็นDogแต่จาวาไม่ได้รับประกันมัน จริงๆแล้ว ณ รันไทม์มันอาจจะแตกต่างกันและจาวาจะโยนClassCastException, ที่จะเกิดขึ้น แน่นอนว่าไม่ใช่ตัวอย่างตัวอย่างที่ดีของคุณ ถ้าคุณจะไม่ทิ้งaไปAnimal, Java ไม่สามารถที่จะรวบรวมแอปพลิเคเพราะไม่ได้มีวิธีการAnimalcallme2()

ในตัวอย่างของคุณไม่สามารถเข้าถึงรหัสของcallme()ของAnimalจากUseAnimlas(เพราะDogเขียนทับได้) เว้นแต่วิธีการที่จะเป็นดังนี้

class Dog extends Animal 
{ 
    public void callme()
    {
        super.callme();
        System.out.println("In callme of Dog");
    }
    ... 
} 

0

เราสามารถสร้างวัตถุเพื่อ Downcasting ในประเภทนี้ยัง : การเรียกเมธอดคลาสพื้นฐาน

Animal a=new Dog();
a.callme();
((Dog)a).callme2();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.