Language-specific · 37
Classes and objects
Bundle data (fields) and behavior (methods) into one blueprint, then make many objects from it.
This lesson is for Python · JavaScript · TypeScript · Java · C# · C++.
C has no classes; it does the same job with structs (struct) and functions (see the structs lesson).
Craykon has no user-defined classes and keeps such data in a Dict(), as in student["name"].
A class is a blueprint, and an object is a real thing built from it.
The example below uses a Student class with a name and a score to make several students, then sorts them by score and prints each with a grade.
class Student: def __init__(self, name, score): self.name = name self.score = score def grade(self): if self.score >= 90: return "A" if self.score >= 80: return "B" return "C" def describe(self): return f"{self.name} {self.score} {self.grade()}" n = int(input())students = []for _ in range(n): name, score = input().split() students.append(Student(name, int(score))) students.sort(key=lambda s: s.score, reverse=True)for s in students: print(s.describe())class Student { constructor(name, score) { this.name = name; this.score = score; } grade() { if (this.score >= 90) return "A"; if (this.score >= 80) return "B"; return "C"; } describe() { return `${this.name} ${this.score} ${this.grade()}`; }} const lines = require("fs").readFileSync(0, "utf8").trim().split("\n");const n = Number(lines[0]);const students = [];for (let i = 1; i <= n; i++) { const [name, score] = lines[i].trim().split(" "); students.push(new Student(name, Number(score)));} students.sort((a, b) => b.score - a.score);for (const s of students) console.log(s.describe());import { readFileSync } from "node:fs"; class Student { readonly name: string; score: number; constructor(name: string, score: number) { this.name = name; this.score = score; } grade(): string { if (this.score >= 90) return "A"; if (this.score >= 80) return "B"; return "C"; } describe(): string { return `${this.name} ${this.score} ${this.grade()}`; }} const lines: string[] = readFileSync(0, "utf8").trim().split("\n");const n: number = Number(lines[0]);const students: Student[] = [];for (let i = 1; i <= n; i++) { const [name, score] = lines[i].trim().split(" "); students.push(new Student(name, Number(score)));} students.sort((a, b) => b.score - a.score);for (const s of students) console.log(s.describe());import java.util.*; class Student { private final String name; private final int score; Student(String name, int score) { this.name = name; this.score = score; } int getScore() { return score; } String grade() { if (score >= 90) return "A"; if (score >= 80) return "B"; return "C"; } String describe() { return name + " " + score + " " + grade(); }} public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); List<Student> students = new ArrayList<>(); for (int i = 0; i < n; i++) { students.add(new Student(sc.next(), sc.nextInt())); } students.sort(Comparator.comparingInt(Student::getScore).reversed()); for (Student s : students) System.out.println(s.describe()); }}using System;using System.Collections.Generic; class Student{ public string Name { get; } public int Score { get; } public Student(string name, int score) { Name = name; Score = score; } public string Grade() { if (Score >= 90) return "A"; if (Score >= 80) return "B"; return "C"; } public string Describe() => $"{Name} {Score} {Grade()}";} class Program{ static void Main() { int n = int.Parse(Console.ReadLine()); var students = new List<Student>(); for (int i = 0; i < n; i++) { string[] parts = Console.ReadLine().Split(' '); students.Add(new Student(parts[0], int.Parse(parts[1]))); } students.Sort((a, b) => b.Score.CompareTo(a.Score)); foreach (var s in students) Console.WriteLine(s.Describe()); }}#include <algorithm>#include <iostream>#include <string>#include <utility>#include <vector> class Student {public: Student(std::string name, int score) : name_(std::move(name)), score_(score) {} int score() const { return score_; } std::string grade() const { if (score_ >= 90) return "A"; if (score_ >= 80) return "B"; return "C"; } std::string describe() const { return name_ + " " + std::to_string(score_) + " " + grade(); } private: std::string name_; int score_;}; int main() { int n; std::cin >> n; std::vector<Student> students; for (int i = 0; i < n; i++) { std::string name; int score; std::cin >> name >> score; students.emplace_back(name, score); } std::sort(students.begin(), students.end(), [](const Student& a, const Student& b) { return a.score() > b.score(); }); for (const Student& s : students) std::cout << s.describe() << '\n';}3 Mina 82 Joon 95 Sora 78
Joon 95 A Mina 82 B Sora 78 C
Key points
- A class lists the data each object holds (fields) and what the object can do (methods).
- The constructor is a special function that fills in the starting values when an object is made.
- Inside a method, the object itself is
this(selfin Python).
When a parameter has the same name, writethis.name = nameto tell them apart. - Access modifiers (
public,private) decide which members outside code may use.
Fields are usually hidden and read through methods or properties. - A list of objects is sorted by a field.
You hand the sort function "what to compare".
How each language writes it
| Python | class Student: with the constructor def __init__(self, name, score):.Fields are made with self.name = name, and every method's first parameter is self.Objects are made without new: Student("Mina", 82).Sort: students.sort(key=lambda s: s.score, reverse=True) |
|---|---|
| JavaScript | class Student { constructor(name, score) { this.name = name; } }.Objects are made with new Student("Mina", 82); leaving out new gives TypeError: Class constructor Student cannot be invoked without 'new'.Sort: students.sort((a, b) => b.score - a.score) |
| TypeScript | Same shape as JavaScript, with fields declared up front, like score: number;.private and readonly are checked only at compile time and vanish at run time.To really hide a field, use JavaScript's private #score |
| Java | The constructor has the class's name and no return type. Fields are hidden with private and read through getters like getScore().With no modifier, a member is visible only inside the same package. Sort: students.sort(Comparator.comparingInt(Student::getScore).reversed()) |
| C# | A property public int Score { get; } is read from outside like a field: s.Score.A member with no modifier is private.Sort: students.Sort((a, b) => b.Score.CompareTo(a.Score)) |
| C++ | class defaults to private and struct to public; that is the only difference, so the example writes public: and private: itself.The constructor fills fields with an initializer list : name_(name), score_(score), and const after a method promises it will not change the object.Objects are values, made without new: Student s("Mina", 82);.Sort: std::sort with the lambda [](const Student& a, const Student& b) { return a.score() > b.score(); } |
Common mistakes
Forgetting self in a methodPython
class Student:
def grade():
return "A"
Student().grade()→ TypeError: Student.grade() takes 0 positional arguments but 1 was given. Writing score without self. inside a method is a NameError
Make self the first parameter and always read fields as self.score.
A list [] as a default valuePython
def __init__(self, name, tags=[]):
self.tags = tags→ That list is made only once, when def runs. A tag added to one student shows up for the others too
Take tags=None and make a new list inside the constructor.
Comparing objects' contents with ==Java · C#
new Student("Mina", 82) == new Student("Mina", 82)→ false — == asks whether they are the same object. Until you override equals, it behaves exactly like ==
Compare contents with equals (Equals in C#), and override that method yourself or use a record.
After
b = a, changing b also changes a in Python, JavaScript, TypeScript, Java and C#, because both names point to the same object.In C++ objects are values, so
Student b = a; and for (Student s : students) make copies; to work on the original, use Student& (or const Student& when you only read).