logo

Programming Languages - Classes

Last Updated: 2024-01-21
  • There is no way to write a Java program without a class.
  • Rust does not have the keyword class, instead it is achieved by struct + impl.
  • Go does not have classes. However, you can define methods on types.

Constructor / Destructor

C++

class Foo {
 public:
  Foo(const Foo& arg);             // copy constructor
  Foo(Foo&& arg);                  // move constructor
  Foo& operator=(const Foo& rhs);  // copy assignment operator
  Foo& operator=(Foo&& rhs);       // move assignment operator

  ~Foo(); // destructor
}

Rust

Constructor:

struct Foo {
  my_field: isize
}

impl Foo {
  // constructor, by convention
  pub fn new(field: isize) -> Foo {
    Foo { my_field: field }
  }
}

Destructor:

fn drop(&mut self);

Java

public class Foo {
  private final int myField;

  // constructor
  public Foo(final int field) {
    this.myField = field;
  }
}

Python

  • constructor: __init__()
  • destructor: __del__(); called when all references to the object have been deleted i.e when an object is garbage collected.

Methods

Go

In Go, a method is just a function, but with a special receiver argument. The (v Vertex) below is the receiver, which means Abs() is not standalone, it has to be called by v.Abs().

type Vertex struct {
	X, Y float64
}

func (v Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
	v := Vertex{3, 4}
	fmt.Println(v.Abs())
}

This is the equivalent function version:

func Abs(v Vertex) float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

You can only declare a method with a receiver whose type is defined in the same package as the method. You cannot declare a method with a receiver whose type is defined in another package

Value receivers vs pointer receivers:

// Value receiver, `Scale()` method operates on a copy of the original `Vertex` value.
func (v Vertex) Scale(f float64) {
	v.X = v.X * f
	v.Y = v.Y * f
}

// Pointer receiver, the values of Vertex will be modified.
func (v *Vertex) Scale(f float64) {
	v.X = v.X * f
	v.Y = v.Y * f
}

When to use pointer receiver:

  1. if the value that the receiver points to will be modified. (e.g. v.X will change within Scale())
  2. if the receiver is a large struct, this avoids copying the whole value.
  3. all methods on a given type should have either value or pointer receivers, but not a mixture of both.

Rust

There's no class; struct doesn’t support methods, use the impl keyword.