2015-06-01 6 views
6

पर विचार करें निम्नलिखित कोड के टुकड़े:सबक्लास से संरक्षित विधि क्यों उपलब्ध नहीं है?

package vehicle; 

public abstract class AbstractVehicle { 
    protected int speedFactor() { 
     return 5; 
    } 
} 

package car; 

import vehicle.AbstractVehicle; 

public class SedanCar extends AbstractVehicle { 
    public static void main(String[] args) { 
     SedanCar sedan = new SedanCar(); 
     sedan 
       .speedFactor(); 
     AbstractVehicle vehicle = new SedanCar(); 
     // vehicle //WON'T compile 
     // .speedFactor(); 
    } 
} 

SedanCarAbstractVehicle का एक उपवर्ग जो एक protected विधि speedFactor होता है। यदि विधि उसी संदर्भ में संदर्भित है तो मैं विधि speedFactor पर कॉल करने में सक्षम हूं। जब संदर्भ के लिए सुपर क्लास का उपयोग किया जाता है तो विधि speedFactor पहुंच योग्य नहीं है।

विधि को छिपाने के लिए क्या कारण है?

+1

'क्योंकि protected' के लिए

If the access is by a qualified name Q.Id, where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S. If the access is by a field access expression E.Id, where E is a Primary expression, or by a method invocation expression E.Id(. . .), where E is a Primary expression, then the access is permitted if and only if the type of E is S or a subclass of S. 

: प्रवेश केवल सी का एक उपवर्ग एस इसके अलावा के शरीर के भीतर की अनुमति दी है, ईद एक दृष्टांत फ़ील्ड या उदाहरण विधि है, तो अर्थ है यदि कक्षा के लिए दृश्यमान है (जैसे 'निजी') और इसके उप-वर्ग। यह ** सार्वजनिक नहीं है **। – EpicPandaForce

+1

'संरक्षित' उदाहरण विधियां कक्षा के लिए दिखाई देती हैं, और subclasses के _instances_ के लिए, लेकिन उपclasses में स्थिर तरीकों के लिए नहीं हैं। – khelwood

+0

लेकिन सेडानकार सारविज्ञान का उप-वर्ग है। – MinusInfinity

उत्तर

4

आपका SedanCar वर्ग AbstractVehicle वर्ग से एक अलग पैकेज में है। protected विधियों को केवल से उसी पैकेज या उप-वर्गों से एक्सेस किया जा सकता है।

SedanCar के मामले में:

SedanCar sedan = new SedanCar(); 
sedan.speedFactor(); 

आप एक ही पैकेज से protected विधि बुला रहे हैं: ठीक है। SedanCar पैकेज car में है और main() विधि एक वर्ग जो पैकेज car में है (वास्तव में एक ही कक्षा) में है।

AbstractVehicle के मामले में:

AbstractVehicle vehicle = new SedanCar(); 
vehicle.speedFactor(); 

आप एक protected विधि कॉल करने की कोशिश लेकिन एक और पैकेज से: नहीं ठीक है। main() जिस विधि से आप इसे कॉल करने का प्रयास करते हैं वह पैकेज car में है जबकि AbstractVehicle पैकेज vehicle में है।

मूल रूप से इस बात को समझ:

आप प्रकार AbstractVehicle जो एक और पैकेज (vehicle) में घोषित किया जाता है के एक चर है। यह गतिशील प्रकार SedanCar हो सकता है या नहीं हो सकता है। आपके मामले में यह करता है, लेकिन यह किसी अन्य पैकेज में परिभाषित किसी अन्य उपclass का उदाहरण भी हो सकता है, उदा। sportcar में। और चूंकि आप पैकेज car (main() विधि) में हैं, तो आप vehicle.speedFactor() आह्वान करने के लिए (जो सुरक्षित है AbstractVehicle.speedFactor()) की अनुमति नहीं है।

+1

मुझे आश्चर्य है कि यह आश्चर्यचकित हो सकता है एक वर्ग से नहीं कहा जा सकता है जो सार Vehicle फैलता है।हां, यह एक स्थिर विधि के अंदर है, लेकिन विधि एक वर्ग द्वारा संलग्न है जो सार Vehicle फैलता है। यह थोड़े समझ में आता है क्योंकि स्थैतिक तरीके विरासत में भाग नहीं लेते हैं, लेकिन यह अभी भी मुझे हैरान है। – markspace

+0

@markspace क्योंकि जिस विधि को आप कॉल करने का प्रयास करते हैं वह 'SedanCar.speedFactor() 'लेकिन' AbstractVehicle.speedFactor() 'नहीं है। हां, वस्तुतः यह 'SedanCar.speedFactor() 'होगा, लेकिन आप' AbstractVehicle.speedFactor() 'का जिक्र कर रहे हैं जो किसी अन्य पैकेज में' संरक्षित 'विधि है। – icza

+0

1.5 दिनों के लिए मेरे एससीजेपी में वापस, एक चीज जिसे मैं याद रखने के लिए इस्तेमाल किया गया था सुपरक्लास संदर्भ चर से सावधान रहना था। अब यह देखना आश्चर्यजनक नहीं है। – prabugp

4

क्योंकि protected वर्ग ही (निजी) की तरह और उसके उपवर्ग उदाहरणों को दिख रहा है। यह सार्वजनिक नहीं है।

उदाहरण के लिए,

package vehicles; 

public abstract class AbstractVehicle { 
    protected int speedFactor() { 
     return 5; 
    } 

    public int getSpeed() { 
     return 10*speedFactor(); //accessing speedFactor() "privately" 
    } 
} 

package vehicles.cars; 

public class SedanCar extends AbstractVehicle { 
    @Override 
    protected int speedFactor() { //overriding protected method (just to show that you can do that) 
     return 10; 
    } 

    @Override 
    public int getSpeed() { 
     return 20*speedFactor(); //this is part of the instance (!!!) therefore it can access speedFactor() protected method too 
    } 
} 

package vehicles.main; 

public class Main { 
    public static void main(String[] args) { 
     AbstractVehicle vehicle = new SedanCar(); 
     int speed = vehicle.getSpeed(); //accessing public method 
     vehicle.speedFactor(); //cannot access protected method from outside class (in another package) 
    } 
} 

स्थिर main() विधि उदाहरण का हिस्सा नहीं है, यही कारण है कि यह संरक्षित विधि का उपयोग नहीं कर सकते हैं।

+0

w.r.t आपकी आखिरी पंक्ति - "स्थैतिक मुख्य() विधि उदाहरण का हिस्सा नहीं है, यही कारण है कि यह संरक्षित विधि तक नहीं पहुंच सकता है।" - यहां तक ​​कि मैं इसे एक गैर स्थैतिक विधि से एक्सेस नहीं कर पा रहा हूं। – Ouney

+0

@ ओनी अच्छी तरह से अगर यह 'सेदानकर' के भीतर एक गैर स्थैतिक विधि है, तो आप इसे एक्सेस करने में सक्षम होना चाहिए। – EpicPandaForce

+0

यही वही है जो मुझे उम्मीद थी लेकिन ऐसा नहीं है :( – Ouney

2

संरक्षित संशोधक निर्दिष्ट करता है कि सदस्य केवल, अपने स्वयं के पैकेज में पहुँचा जा सकता है और, इसके अलावा में (पैकेज-निजी के साथ के रूप में) एक और पैकेज में अपने वर्ग का एक उपवर्ग से।

यही वजह है कि आप सीधे वाहन वस्तु पर मुख्य विधि के अंदर विधि कॉल नहीं कर सकता है।

देखें: https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

+0

लेकिन कोड काम करता है, SedanCar sedan = new SedanCar(); sedan.speedFactor() – MinusInfinity

+1

काम करता है क्योंकि यह उसी जावा पैकेज में घोषित किया गया है –

0

जावा 1.5 दिनों के लिए मेरे एससीजेपी में वापस, एक चीज जो मुझे याद रखने के लिए उपयोग की गई थी, सुपरक्लास संदर्भ चर से सावधान रहना था। यह अब देखने के लिए आश्चर्यजनक नहीं है और एक बात यह भ्रमित क्यों हो रही है कि नियम संरक्षित है उप-वर्ग या एक ही पैकेज के लिए दृश्यमान है। क्या होगा यदि यह सबक्लास और अलग पैकेज दोनों है?

यदि आप किसी अन्य पैकेज बनाते हैं, और करते हैं

package yetAnotherPackage; 

import car.SedanCar; 

public class Main { 

    public static void main(String[] args) { 
     new SedanCar().speedFactor(); 
    } 

} 

आपको लगता है कि

The method speedFactor() from the type AbstractVehicle is not visible 

ऐसा लगता है कि शासन सिर्फ प्रसारित देखेंगे। जब तक आपके पास उप-वर्ग हो और उप-वर्ग के पैकेज में संरक्षित विधि तक पहुंचने का प्रयास करें (या यदि कोई सबक्लास नहीं है, तो माता-पिता का पैकेज), तो आपको अच्छा होना चाहिए।

0

विभिन्न पैकेज में उप-वर्ग सुपरक्लास संदर्भ का उपयोग कर सुपरक्लास से सुरक्षित विधियों और संरक्षित चर तक नहीं पहुंच सकते हैं। उपवर्ग में सुपर क्लास के संरक्षित डेटा का उपयोग करने केवल जिस तरह से विरासत के माध्यम से है नीचे

दो कोड स्निपेट

package nee; 
import parentdata.Parent; 

class Child extends Parent{ 

     public void testIt(){ 
     System.out.println(x); // able to access protected x defined in Parent 
     } 

    } 


package nee; 
import parentdata.Parent; 

     class Child extends Parent { 

     public void testIt(){ 
     Parent p=new Parent(); 
     System.out.println(p.x) // results in compile time error 
     } 

    } 

भाषा विनिर्देश में 6.6.2.1 एक संरक्षित सदस्य तक पहुंच

Let सी हो रहे हैं कक्षा जिसमें एक संरक्षित सदस्य एम घोषित किया जाता है। में गहराई विवरण का दौरा http://www.jot.fm/issues/issue_2005_10/article3.pdf

संबंधित मुद्दे