I wanted to create a method that only works where the self
parameter was an Rc
. I saw that I could use Box
, so I thought I might try to mimic how that works:
use std::rc::Rc; use std::sync::Arc; struct Bar; impl Bar { fn consuming(self) {} fn reference(&self) {} fn mutable_reference(&mut self) {} fn boxed(self: Box<Bar>) {} fn ref_count(self: Rc<Bar>) {} fn atomic_ref_count(self: Arc<Bar>) {} } fn main() {}
Yields these errors:
error[E0308]: mismatched method receiver --> a.rs:11:18 | 11 | fn ref_count(self: Rc<Bar>) {} | ^^^^ expected struct `Bar`, found struct `std::rc::Rc` | = note: expected type `Bar` = note: found type `std::rc::Rc<Bar>` error[E0308]: mismatched method receiver --> a.rs:12:25 | 12 | fn atomic_ref_count(self: Arc<Bar>) {} | ^^^^ expected struct `Bar`, found struct `std::sync::Arc` | = note: expected type `Bar` = note: found type `std::sync::Arc<Bar>`
This is with Rust 1.15.1.
The self parameter is a reference to the current instance of the class, and is used to access variables that belongs to the class.
The self is used to represent the instance of the class. With this keyword, you can access the attributes and methods of the class in python. It binds the attributes with the given arguments. The reason why we use self is that Python does not use the '@' syntax to refer to instance attributes.
The self variable is used to represent the instance of the class which is often used in object-oriented programming. It works as a reference to the object. Python uses the self parameter to refer to instance attributes and methods of the class.
The self keyword is used to represent an instance (object) of the given class. In this case, the two Cat objects cat1 and cat2 have their own name and age attributes. If there was no self argument, the same class couldn't hold the information for both these objects.
If you have been programming in Python (object-oriented programming) for some time, then you have definitely come across methods that have self as their first parameter. Let us first try to understand what this recurring self parameter is. What is self in Python?
All instance methods take the first parameter self and the value of self is automatically given by Python. The parameter self, similar to a pointer in C language, references to the current object of the class. Using self, instance methods can access and alter the state/attributes of an object.
Our two class methods have a common parameter cls. All class methods take the first parameter cls. The parameter cls references to the Class. Since cls parameter references to the class, it can access and modify only the class state.
Self is the first argument to be passed in Constructor and Instance Method. Self must be provided as a First parameter to the Instance method and constructor. If you don’t provide it, it will cause an error. Self is a convention and not a Python keyword . self is parameter in Instance Method and user can use another parameter name in place of it.
Before Rust 1.33, there are only four valid method receivers:
struct Foo; impl Foo { fn by_val(self: Foo) {} // a.k.a. by_val(self) fn by_ref(self: &Foo) {} // a.k.a. by_ref(&self) fn by_mut_ref(self: &mut Foo) {} // a.k.a. by_mut_ref(&mut self) fn by_box(self: Box<Foo>) {} // no short form } fn main() {}
Originally, Rust didn't have this explicit self
form, only self
, &self
, &mut self
and ~self
(the old name for Box
). This changed so that only by-value and by-references have the short-hand built-in syntax, since they are the common cases, and have very key language properties, while all smart pointers (including Box
) require the explicit form.
As of Rust 1.33, some additional selected types are available for use as self
:
Rc
Arc
Pin
This means that the original example now works:
use std::{rc::Rc, sync::Arc}; struct Bar; impl Bar { fn consuming(self) { println!("self") } fn reference(&self) { println!("&self") } fn mut_reference(&mut self) { println!("&mut self") } fn boxed(self: Box<Bar>) { println!("Box") } fn ref_count(self: Rc<Bar>) { println!("Rc") } fn atomic_ref_count(self: Arc<Bar>) { println!("Arc") } } fn main() { Bar.consuming(); Bar.reference(); Bar.mut_reference(); Box::new(Bar).boxed(); Rc::new(Bar).ref_count(); Arc::new(Bar).atomic_ref_count(); }
However, the impl
handling hasn't yet been fully generalised to match the syntax, so user-created types still don't work. Progress on this is being made under the feature flag arbitrary_self_types
and discussion is taking place in the tracking issue 44874.
(Something to look forward to!)
It's now possible to use arbitrary types for self
, including Arc<Self>
, but the feature is considered unstable and thus requires adding this crate attribute:
#![feature(arbitrary_self_types)]
Using feature
crate attributes requires using nightly Rust.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With