Java Language
वर्ग और वस्तुएँ
खोज…
परिचय
वस्तुओं में अवस्थाएँ और व्यवहार होते हैं। उदाहरण: एक कुत्ते के पास राज्य है - रंग, नाम, नस्ल के साथ-साथ व्यवहार - पूंछ को छेड़ना, भौंकना, खाना। एक वस्तु एक वर्ग का एक उदाहरण है।
वर्ग - एक वर्ग को एक टेम्पलेट / ब्लूप्रिंट के रूप में परिभाषित किया जा सकता है जो उस व्यवहार / स्थिति का वर्णन करता है जो उसके प्रकार के समर्थन का उद्देश्य है।
वाक्य - विन्यास
- क्लास उदाहरण {} // क्लास कीवर्ड, नाम, बॉडी
सरलतम संभव वर्ग
class TrivialClass {}
एक वर्ग में न्यूनतम class
कीवर्ड, एक नाम और एक निकाय होता है, जो खाली हो सकता है।
आप new
ऑपरेटर के साथ एक वर्ग को तुरंत टाइप करते हैं।
TrivialClass tc = new TrivialClass();
वस्तु सदस्य बनाम स्थैतिक सदस्य
इस वर्ग के साथ:
class ObjectMemberVsStaticMember {
static int staticCounter = 0;
int memberCounter = 0;
void increment() {
staticCounter ++;
memberCounter++;
}
}
निम्नलिखित कोड स्निपेट:
final ObjectMemberVsStaticMember o1 = new ObjectMemberVsStaticMember();
final ObjectMemberVsStaticMember o2 = new ObjectMemberVsStaticMember();
o1.increment();
o2.increment();
o2.increment();
System.out.println("o1 static counter " + o1.staticCounter);
System.out.println("o1 member counter " + o1.memberCounter);
System.out.println();
System.out.println("o2 static counter " + o2.staticCounter);
System.out.println("o2 member counter " + o2.memberCounter);
System.out.println();
System.out.println("ObjectMemberVsStaticMember.staticCounter = " + ObjectMemberVsStaticMember.staticCounter);
// the following line does not compile. You need an object
// to access its members
//System.out.println("ObjectMemberVsStaticMember.staticCounter = " + ObjectMemberVsStaticMember.memberCounter);
इस उत्पादन का उत्पादन:
o1 static counter 3
o1 member counter 1
o2 static counter 3
o2 member counter 2
ObjectMemberVsStaticMember.staticCounter = 3
नोट: आपको static
सदस्यों को वस्तुओं पर नहीं, बल्कि कक्षाओं में बुलाना चाहिए। हालांकि यह JVM के लिए कोई फर्क नहीं पड़ता है, मानव पाठक इसकी सराहना करेंगे।
static
सदस्य वर्ग का हिस्सा हैं और प्रति कक्षा केवल एक बार मौजूद हैं। गैर- static
सदस्य उदाहरणों पर मौजूद होते हैं, प्रत्येक उदाहरण के लिए एक स्वतंत्र प्रतिलिपि होती है। इसका अर्थ यह भी है कि आपको अपने सदस्यों तक पहुँचने के लिए उस वर्ग की किसी वस्तु तक पहुँच की आवश्यकता होती है।
ओवरलोडिंग के तरीके
कभी-कभी एक ही कार्यक्षमता को विभिन्न प्रकार के इनपुट के लिए लिखना पड़ता है। उस समय, कोई एक ही विधि नाम का उपयोग विभिन्न मापदंडों के सेट के साथ कर सकता है। मापदंडों के प्रत्येक अलग सेट को एक विधि हस्ताक्षर के रूप में जाना जाता है। उदाहरण के अनुसार, एक एकल विधि में कई हस्ताक्षर हो सकते हैं।
public class Displayer {
public void displayName(String firstName) {
System.out.println("Name is: " + firstName);
}
public void displayName(String firstName, String lastName) {
System.out.println("Name is: " + firstName + " " + lastName);
}
public static void main(String[] args) {
Displayer displayer = new Displayer();
displayer.displayName("Ram"); //prints "Name is: Ram"
displayer.displayName("Jon", "Skeet"); //prints "Name is: Jon Skeet"
}
}
लाभ यह है कि एक ही कार्यक्षमता को दो अलग-अलग संख्याओं के इनपुट के साथ कहा जाता है। हम जिस इनपुट से गुजर रहे हैं, उसके अनुसार विधि को लागू करते समय (इस स्थिति में या तो एक स्ट्रिंग मान या दो स्ट्रिंग मान) संबंधित विधि निष्पादित होती है।
तरीके अतिभारित किए जा सकते हैं:
पारित किए गए मापदंडों की संख्या के आधार पर।
उदाहरण:
method(String s)
औरmethod(String s1, String s2)
।
मापदंडों के क्रम के आधार पर।
उदाहरण:
method(int i, float f)
औरmethod(float f, int i))
।
नोट: तरीकों को केवल रिटर्न प्रकार ( int method()
को String method()
रूप में ही माना जाता है int method()
ओवरलोड नहीं किया जा सकता है String method()
और यदि प्रयास किया गया तो RuntimeException
को फेंक दिया जाएगा)। यदि आप रिटर्न प्रकार बदलते हैं तो आपको अधिभार के क्रम में मापदंडों को भी बदलना होगा।
मूल वस्तु निर्माण और उपयोग
वस्तुएं अपनी कक्षा में आती हैं, इसलिए एक सरल उदाहरण एक कार होगी (नीचे विस्तृत विवरण):
public class Car {
//Variables describing the characteristics of an individual car, varies per object
private int milesPerGallon;
private String name;
private String color;
public int numGallonsInTank;
public Car(){
milesPerGallon = 0;
name = "";
color = "";
numGallonsInTank = 0;
}
//this is where an individual object is created
public Car(int mpg, int, gallonsInTank, String carName, String carColor){
milesPerGallon = mpg;
name = carName;
color = carColor;
numGallonsInTank = gallonsInTank;
}
//methods to make the object more usable
//Cars need to drive
public void drive(int distanceInMiles){
//get miles left in car
int miles = numGallonsInTank * milesPerGallon;
//check that car has enough gas to drive distanceInMiles
if (miles <= distanceInMiles){
numGallonsInTank = numGallonsInTank - (distanceInMiles / milesPerGallon)
System.out.println("Drove " + numGallonsInTank + " miles!");
} else {
System.out.println("Could not drive!");
}
}
public void paintCar(String newColor){
color = newColor;
}
//set new Miles Per Gallon
public void setMPG(int newMPG){
milesPerGallon = newMPG;
}
//set new number of Gallon In Tank
public void setGallonsInTank(int numGallons){
numGallonsInTank = numGallons;
}
public void nameCar(String newName){
name = newName;
}
//Get the Car color
public String getColor(){
return color;
}
//Get the Car name
public String getName(){
return name;
}
//Get the number of Gallons
public String getGallons(){
return numGallonsInTank;
}
}
वस्तुएं उनके वर्ग के उदाहरण हैं। तो, जिस तरह से आप एक ऑब्जेक्ट बनाएंगे वह आपके मुख्य वर्ग (जावा में मुख्य विधि या एंड्रॉइड में ऑनक्रिएट) में दो तरीकों में से एक में कार क्लास को कॉल करके होगा।
विकल्प 1
`Car newCar = new Car(30, 10, "Ferrari", "Red");
विकल्प 1 वह जगह है जहां आप अनिवार्य रूप से ऑब्जेक्ट के निर्माण पर कार के बारे में सब कुछ कार्यक्रम को बताते हैं। कार की किसी भी संपत्ति को बदलने के लिए repaintCar
विधि जैसे तरीकों में से एक को कॉल करना होगा। उदाहरण:
newCar.repaintCar("Blue");
नोट: सुनिश्चित करें कि आप विधि के लिए सही डेटा प्रकार पास करते हैं। ऊपर दिए गए उदाहरण में, जब तक डेटा प्रकार सही नहीं है तब तक आप एक चर को repaintCar
विधि में भी पास कर सकते हैं।
यह एक वस्तु के गुणों को बदलने का एक उदाहरण था, किसी वस्तु के गुणों को प्राप्त करने के लिए कार वर्ग से एक विधि का उपयोग करना होगा जिसमें रिटर्न वैल्यू है (जिसका अर्थ है एक विधि जो void
नहीं void
)। उदाहरण:
String myCarName = newCar.getName(); //returns string "Ferrari"
विकल्प 1 सबसे अच्छा विकल्प है जब आपके पास निर्माण के समय सभी ऑब्जेक्ट का डेटा होता है।
विकल्प 2
`Car newCar = new Car();
विकल्प 2 को एक ही प्रभाव प्राप्त होता है लेकिन किसी वस्तु को सही ढंग से बनाने के लिए अधिक कार्य की आवश्यकता होती है। मैं इस कंस्ट्रक्टर को कार क्लास में वापस बुलाना चाहता हूं:
public void Car(){
milesPerGallon = 0;
name = "";
color = "";
numGallonsInTank = 0;
}
ध्यान दें कि आपको वास्तव में इसे बनाने के लिए किसी भी पैरामीटर को ऑब्जेक्ट में पास नहीं करना है। यह तब बहुत उपयोगी होता है जब आपके पास ऑब्जेक्ट के सभी पहलू नहीं होते हैं, लेकिन आपको उन हिस्सों का उपयोग करने की आवश्यकता होती है जो आपके पास होते हैं। यह ऑब्जेक्ट के प्रत्येक उदाहरण चर में जेनेरिक डेटा सेट करता है ताकि, यदि आप उस डेटा के टुकड़े के लिए कॉल करें जो मौजूद नहीं है, तो कोई त्रुटि नहीं है।
नोट: यह मत भूलो कि आपको ऑब्जेक्ट के हिस्सों को बाद में सेट करना है जो आपने इसके साथ प्रारंभ नहीं किया था। उदाहरण के लिए,
Car myCar = new Car();
String color = Car.getColor(); //returns empty string
यह उन वस्तुओं में एक आम गलती है जो उनके सभी डेटा के साथ आरंभिक नहीं हैं। त्रुटियों से बचा गया क्योंकि एक कंस्ट्रक्टर है जो स्टैंड-इन चर ( public Car(){}
) के साथ एक खाली कार ऑब्जेक्ट को बनाने की अनुमति देता है, लेकिन माइकर का कोई भी हिस्सा वास्तव में अनुकूलित नहीं था। कार ऑब्जेक्ट बनाने का सही उदाहरण:
Car myCar = new Car();
myCar.nameCar("Ferrari");
myCar.paintCar("Purple");
myCar.setGallonsInTank(10);
myCar.setMPG(30);
और, एक अनुस्मारक के रूप में, अपने मुख्य वर्ग में एक विधि को कॉल करके किसी ऑब्जेक्ट के गुण प्राप्त करें। उदाहरण:
String myCarName = myCar.getName(); //returns string "Ferrari"
कंस्ट्रक्टर्स
निर्माता वर्ग के नाम पर और वापसी प्रकार के बिना विशेष तरीके हैं, और वस्तुओं का निर्माण करने के लिए उपयोग किया जाता है। निर्माता, विधियों की तरह, इनपुट पैरामीटर ले सकते हैं। कन्स्ट्रक्टर्स का उपयोग वस्तुओं को इनिशियलाइज़ करने के लिए किया जाता है। एब्सट्रैक्ट क्लासेस में कंस्ट्रक्टर भी हो सकते हैं।
public class Hello{
// constructor
public Hello(String wordToPrint){
printHello(wordToPrint);
}
public void printHello(String word){
System.out.println(word);
}
}
// instantiates the object during creating and prints out the content
// of wordToPrint
यह समझना महत्वपूर्ण है कि निर्माणकर्ता कई तरीकों से अलग हैं:
कंस्ट्रक्टर्स केवल संशोधक को
public
,private
औरprotected
कर सकते हैं, और उन्हेंabstract
,final
,static
याsynchronized
घोषित नहीं किया जा सकता है।कंस्ट्रक्टर्स के पास रिटर्न टाइप नहीं है।
कन्स्ट्रक्टर्स को क्लास के नाम के समान होना चाहिए।
Hello
उदाहरण में,Hello
ऑब्जेक्ट का निर्माता नाम वर्ग नाम के समान है।this
कीवर्ड का निर्माणकर्ताओं के अंदर एक अतिरिक्त उपयोग है।this.method(...)
वर्तमान उदाहरण पर एक विधि कहता है, जबकिthis(...)
वर्तमान हस्ताक्षर में किसी अन्य निर्माता को संदर्भित करता है।
कीवर्ड super
का उपयोग करके कंस्ट्रक्टर्स को विरासत के माध्यम से भी बुलाया जा सकता है।
public class SuperManClass{
public SuperManClass(){
// some implementation
}
// ... methods
}
public class BatmanClass extends SupermanClass{
public BatmanClass(){
super();
}
//... methods...
}
जावा लैंग्वेज स्पेसिफिकेशन # 8.8 और # 15.9 देखें
स्टैटिक इनिशियलाइज़र का उपयोग करके स्टैटिक फ़ाइनल फ़ील्ड को आरम्भ करना
एक static final
फ़ील्ड को आरंभ करने के लिए जिसे एक से अधिक अभिव्यक्ति का उपयोग करने की आवश्यकता होती है, एक static
इनिशियलाइज़र का उपयोग मूल्य को निर्दिष्ट करने के लिए किया जा सकता है। निम्न उदाहरण String
s के एक अपरिवर्तनीय सेट को आरंभ करता है:
public class MyClass {
public static final Set<String> WORDS;
static {
Set<String> set = new HashSet<>();
set.add("Hello");
set.add("World");
set.add("foo");
set.add("bar");
set.add("42");
WORDS = Collections.unmodifiableSet(set);
}
}
ओवरलोडिंग और ओवरराइडिंग की विधि क्या है, इसकी व्याख्या करना।
मेथड ओवरराइडिंग और ओवरलोडिंग, जावा द्वारा समर्थित बहुरूपता के दो रूप हैं।
विधि ओवरलोडिंग
विधि अधिभार (जिसे स्थैतिक बहुरूपता के रूप में भी जाना जाता है) एक ऐसा तरीका है जिसमें आप एक ही वर्ग में एक ही नाम के साथ दो (या अधिक) तरीके (कार्य) कर सकते हैं। हाँ, यह उतना ही सरल है।
public class Shape{
//It could be a circle or rectangle or square
private String type;
//To calculate area of rectangle
public Double area(Long length, Long breadth){
return (Double) length * breadth;
}
//To calculate area of a circle
public Double area(Long radius){
return (Double) 3.14 * r * r;
}
}
इस तरह उपयोगकर्ता उस क्षेत्र के लिए उसी विधि को कॉल कर सकता है जो उसके आकार के प्रकार पर निर्भर करता है।
लेकिन अब असली सवाल यह है कि जावा कंपाइलर यह कैसे भेद करेगा कि किस विधि को निष्पादित किया जाना है?
खैर जावा ने यह स्पष्ट कर दिया है कि भले ही विधि के नाम (हमारे मामले में area()
समान हों, लेकिन तर्कों का तरीका अलग होना चाहिए।
अतिभारित तरीकों में अलग-अलग तर्क सूची (मात्रा और प्रकार) होनी चाहिए।
कहा जा रहा है कि हम इस तरह के वर्ग के क्षेत्र की गणना करने के लिए एक और तरीका नहीं जोड़ सकते हैं: public Double area(Long side)
क्योंकि इस मामले में, यह सर्कल के क्षेत्र विधि के साथ संघर्ष करेगा और जावा कंपाइलर के लिए अस्पष्टता का कारण होगा।
भगवान का शुक्र है, ओवरलोड तरीके लिखने जैसे कुछ आराम हैं
अलग-अलग रिटर्न प्रकार हो सकते हैं।
अलग पहुँच संशोधक हो सकते हैं।
अलग-अलग अपवादों को फेंक सकते हैं।
इसे स्थैतिक बहुरूपता क्यों कहा जाता है?
खैर ऐसा इसलिए है क्योंकि जिन अतिभारित तरीकों को लागू किया जाना है, उनका संकलन समय पर किया जाता है, जो तर्कों की वास्तविक संख्या और तर्कों के संकलन-समय के आधार पर किया जाता है।
विधि अधिभार का उपयोग करने के सामान्य कारणों में से एक कोड की सरलता है जो इसे प्रदान करता है। उदाहरण के लिए
String.valueOf()
याद रखें जो लगभग किसी भी प्रकार का तर्क लेता है? दृश्य के पीछे जो लिखा गया है वह शायद कुछ इस प्रकार है: -
static String valueOf(boolean b)
static String valueOf(char c)
static String valueOf(char[] data)
static String valueOf(char[] data, int offset, int count)
static String valueOf(double d)
static String valueOf(float f)
static String valueOf(int i)
static String valueOf(long l)
static String valueOf(Object obj)
तरीका ओवरराइडिंग
अच्छी तरह से, विधि ओवरराइडिंग (हाँ आप इसे सही मानते हैं, इसे गतिशील बहुरूपता के रूप में भी जाना जाता है) कुछ अधिक दिलचस्प और जटिल विषय है।
ओवरराइड करने की विधि में हम मूल वर्ग द्वारा प्रदान की गई विधि निकाय को अधिलेखित कर देते हैं। समझ गया? नहीं? एक उदाहरण के माध्यम से चलते हैं।
public abstract class Shape{
public abstract Double area(){
return 0.0;
}
}
इसलिए हमारे पास आकृति नामक एक वर्ग है और इसमें विधि नामक क्षेत्र है जो संभवतः आकृति के क्षेत्र को लौटा देगा।
मान लीजिए कि अब हमारे पास सर्कल और आयत नामक दो कक्षाएं हैं।
public class Circle extends Shape {
private Double radius = 5.0;
// See this annotation @Override, it is telling that this method is from parent
// class Shape and is overridden here
@Override
public Double area(){
return 3.14 * radius * radius;
}
}
इसी तरह आयत श्रेणी:
public class Rectangle extends Shape {
private Double length = 5.0;
private Double breadth= 10.0;
// See this annotation @Override, it is telling that this method is from parent
// class Shape and is overridden here
@Override
public Double area(){
return length * breadth;
}
}
तो, अब आपके दोनों बच्चों की कक्षाओं में माता-पिता ( Shape
) वर्ग द्वारा प्रदान की गई अपडेट बॉडी है। अब सवाल यह है कि परिणाम कैसे देखें? अच्छी तरह से यह पुराने psvm
तरीका है।
public class AreaFinder{
public static void main(String[] args){
//This will create an object of circle class
Shape circle = new Circle();
//This will create an object of Rectangle class
Shape rectangle = new Rectangle();
// Drumbeats ......
//This should print 78.5
System.out.println("Shape of circle : "+circle.area());
//This should print 50.0
System.out.println("Shape of rectangle: "+rectangle.area());
}
}
वाह! यह बहुत अच्छा नहीं है? एक ही प्रकार की दो वस्तुएं एक ही तरीके की कॉलिंग और विभिन्न मान लौटाती हैं। मेरे मित्र, यह गतिशील बहुरूपता की शक्ति है।
इन दोनों के बीच अंतर की तुलना करने के लिए यहां एक चार्ट दिया गया है: -
विधि अतिभार | विधि ओवरराइडिंग |
---|---|
प्रोग्राम की पठनीयता बढ़ाने के लिए मेथड ओवरलोडिंग का उपयोग किया जाता है। | विधि के ओवरराइडिंग का उपयोग उस विधि के विशिष्ट कार्यान्वयन को प्रदान करने के लिए किया जाता है जो पहले से ही अपने सुपर क्लास द्वारा प्रदान की जाती है। |
विधि अधिभार वर्ग के भीतर किया जाता है। | ओवरराइडिंग विधि दो वर्गों में होती है जिनमें आईएस-ए (वंशानुक्रम) संबंध होता है। |
विधि अधिभार के मामले में, पैरामीटर अलग होना चाहिए। | ओवरराइडिंग विधि के मामले में, पैरामीटर समान होना चाहिए। |
विधि अधिभार संकलित समय बहुरूपता का उदाहरण है। | विधि ओवरराइडिंग रन टाइम बहुरूपता का उदाहरण है। |
जावा में, केवल विधि के रिटर्न प्रकार को बदलकर विधि अधिभार नहीं किया जा सकता है। ओवरलोडिंग में रिटर्न टाइप एक ही या अलग हो सकता है। लेकिन आपको पैरामीटर बदलना होगा। | ओवरराइडिंग विधि में रिटर्न प्रकार समान या सहसंयोजक होना चाहिए। |