Rust
वस्तु-उन्मुख जंग
खोज…
परिचय
जंग वस्तु उन्मुख है कि इसके बीजीय डेटा प्रकारों में संबद्ध विधियां हो सकती हैं, जिससे वे कोड के साथ संग्रहीत डेटा के अर्थ में ऑब्जेक्ट बनाते हैं जो जानता है कि इसके साथ कैसे काम करना है।
जंग, हालांकि, उत्तराधिकार का समर्थन नहीं करता है, जो ट्रिट्स के साथ रचना का समर्थन करता है। इसका मतलब यह है कि कई OO पैटर्न काम नहीं करते हैं और उन्हें संशोधित किया जाना चाहिए। कुछ पूरी तरह अप्रासंगिक हैं।
लक्षण के साथ विरासत
जंग में, एक संरचना के गुणों को "विरासत" करने की कोई अवधारणा नहीं है। इसके बजाय, जब आप वस्तुओं के बीच के संबंध को डिजाइन कर रहे होते हैं, तो यह इस तरह से होता है कि किसी की कार्यक्षमता को इंटरफ़ेस (रस्ट में एक विशेषता ) द्वारा परिभाषित किया जाता है। यह विरासत पर रचना को बढ़ावा देता है, जिसे बड़ी परियोजनाओं के लिए अधिक उपयोगी और आसान माना जाता है।
यहाँ पायथन में कुछ उदाहरण विरासत का उपयोग करके एक उदाहरण दिया गया है:
class Animal:
def speak(self):
print("The " + self.animal_type + " said " + self.noise)
class Dog(Animal):
def __init__(self):
self.animal_type = 'dog'
self.noise = 'woof'
रुस्त में इसका अनुवाद करने के लिए, हमें एक जानवर को बनाने और उस कार्यक्षमता को लक्षणों में रखने की ज़रूरत है।
trait Speaks {
fn speak(&self);
fn noise(&self) -> &str;
}
trait Animal {
fn animal_type(&self) -> &str;
}
struct Dog {}
impl Animal for Dog {
fn animal_type(&self) -> &str {
"dog"
}
}
impl Speaks for Dog {
fn speak(&self) {
println!("The dog said {}", self.noise());
}
fn noise(&self) -> &str {
"woof"
}
}
fn main() {
let dog = Dog {};
dog.speak();
}
ध्यान दें कि हमने उस अमूर्त अभिभावक वर्ग को दो अलग-अलग घटकों में कैसे तोड़ा: वह भाग जो संरचना को एक जानवर के रूप में परिभाषित करता है, और वह भाग जो इसे बोलने की अनुमति देता है।
सूक्ष्म पाठक यह नोटिस करेंगे कि यह एक से एक नहीं है, क्योंकि प्रत्येक कार्यान्वयनकर्ता को "द {जानवर} ने कहा {शोर}" के रूप में एक स्ट्रिंग को प्रिंट करने के लिए तर्क को फिर से लागू करना होगा। आप इसे इंटरफ़ेस के एक मामूली रिडिजाइन के साथ कर सकते हैं जहाँ हम Speak
for Animal
कार्यान्वित करते हैं:
trait Speaks {
fn speak(&self);
}
trait Animal {
fn animal_type(&self) -> &str;
fn noise(&self) -> &str;
}
impl<T> Speaks for T where T: Animal {
fn speak(&self) {
println!("The {} said {}", self.animal_type(), self.noise());
}
}
struct Dog {}
struct Cat {}
impl Animal for Dog {
fn animal_type(&self) -> &str {
"dog"
}
fn noise(&self) -> &str {
"woof"
}
}
impl Animal for Cat {
fn animal_type(&self) -> &str {
"cat"
}
fn noise(&self) -> &str {
"meow"
}
}
fn main() {
let dog = Dog {};
let cat = Cat {};
dog.speak();
cat.speak();
}
गौर करें कि अब जानवर शोर मचाता है और बोलता है कि अब जानवरों के लिए कुछ भी लागू करना है। यह पिछले तरीके और पायथन विरासत दोनों की तुलना में बहुत अधिक लचीला है। उदाहरण के लिए, यदि आप एक ऐसी Human
जोड़ना चाहते हैं जिसमें एक अलग ध्वनि है, तो हम इसके बजाय कुछ Human
लिए speak
का एक और कार्यान्वयन कर सकते हैं:
trait Human {
fn name(&self) -> &str;
fn sentence(&self) -> &str;
}
struct Person {}
impl<T> Speaks for T where T: Human {
fn speak(&self) {
println!("{} said {}", self.name(), self.sentence());
}
}
आगंतुक पैटर्न
जावा में विशिष्ट आगंतुक उदाहरण होगा:
interface ShapeVisitor {
void visit(Circle c);
void visit(Rectangle r);
}
interface Shape {
void accept(ShapeVisitor sv);
}
class Circle implements Shape {
private Point center;
private double radius;
public Circle(Point center, double radius) {
this.center = center;
this.radius = radius;
}
public Point getCenter() { return center; }
public double getRadius() { return radius; }
@Override
public void accept(ShapeVisitor sv) {
sv.visit(this);
}
}
class Rectangle implements Shape {
private Point lowerLeftCorner;
private Point upperRightCorner;
public Rectangle(Point lowerLeftCorner, Point upperRightCorner) {
this.lowerLeftCorner = lowerLeftCorner;
this.upperRightCorner = upperRightCorner;
}
public double length() { ... }
public double width() { ... }
@Override
public void accept(ShapeVisitor sv) {
sv.visit(this);
}
}
class AreaCalculator implements ShapeVisitor {
private double area = 0.0;
public double getArea() { return area; }
public void visit(Circle c) {
area = Math.PI * c.radius() * c.radius();
}
public void visit(Rectangle r) {
area = r.length() * r.width();
}
}
double computeArea(Shape s) {
AreaCalculator ac = new AreaCalculator();
s.accept(ac);
return ac.getArea();
}
यह आसानी से दो तरह से रस्ट का अनुवाद किया जा सकता है।
पहला तरीका रन-टाइम बहुरूपता का उपयोग करता है:
trait ShapeVisitor {
fn visit_circle(&mut self, c: &Circle);
fn visit_rectangle(&mut self, r: &Rectangle);
}
trait Shape {
fn accept(&self, sv: &mut ShapeVisitor);
}
struct Circle {
center: Point,
radius: f64,
}
struct Rectangle {
lowerLeftCorner: Point,
upperRightCorner: Point,
}
impl Shape for Circle {
fn accept(&self, sv: &mut ShapeVisitor) {
sv.visit_circle(self);
}
}
impl Rectangle {
fn length() -> double { ... }
fn width() -> double { ... }
}
impl Shape for Rectangle {
fn accept(&self, sv: &mut ShapeVisitor) {
sv.visit_rectangle(self);
}
}
fn computeArea(s: &Shape) -> f64 {
struct AreaCalculator {
area: f64,
}
impl ShapeVisitor for AreaCalculator {
fn visit_circle(&mut self, c: &Circle) {
self.area = std::f64::consts::PI * c.radius * c.radius;
}
fn visit_rectangle(&mut self, r: &Rectangle) {
self.area = r.length() * r.width();
}
}
let mut ac = AreaCalculator { area: 0.0 };
s.accept(&mut ac);
ac.area
}
इसके बजाय दूसरा तरीका संकलन-समय के बहुरूपता का उपयोग करता है, केवल अंतर यहां दिखाए गए हैं:
trait Shape {
fn accept<V: ShapeVisitor>(&self, sv: &mut V);
}
impl Shape for Circle {
fn accept<V: ShapeVisitor>(&self, sv: &mut V) {
// same body
}
}
impl Shape for Rectangle {
fn accept<V: ShapeVisitor>(&self, sv: &mut V) {
// same body
}
}
fn computeArea<S: Shape>(s: &S) -> f64 {
// same body
}