Classes e POO
Conceitos de Programação Orientada a Objetos variam entre linguagens. Veja como classes, herança, interfaces e polimorfismo funcionam em diferentes linguagens.
Definição de Classe e Instanciação
- JavaScript
- PHP
- Rust
- Go
- Python
- Zig
- C#
- C++
- C
- Java
- Ruby
- Swift
// ES6 Classes
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, I'm ${this.name}`;
}
}
// Instantiation
const person = new Person("John", 30);
// Inheritance
class Student extends Person {
constructor(name, age, school) {
super(name, age);
this.school = school;
}
study() {
return `${this.name} is studying`;
}
}
<?php
// Class definition
class Person {
private $name;
private $age;
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
}
public function greet() {
return "Hello, I'm " . $this->name;
}
}
// Instantiation
$person = new Person("John", 30);
// Inheritance
class Student extends Person {
private $school;
public function __construct($name, $age, $school) {
parent::__construct($name, $age);
$this->school = $school;
}
public function study() {
return $this->name . " is studying";
}
}
// Structs with impl blocks
struct Person {
name: String,
age: u32,
}
impl Person {
fn new(name: String, age: u32) -> Person {
Person { name, age }
}
fn greet(&self) -> String {
format!("Hello, I'm {}", self.name)
}
}
// Traits (similar to interfaces)
trait Greetable {
fn greet(&self) -> String;
}
impl Greetable for Person {
fn greet(&self) -> String {
format!("Hello, I'm {}", self.name)
}
}
// Structs with methods
type Person struct {
name string
age int
}
func NewPerson(name string, age int) *Person {
return &Person{name: name, age: age}
}
func (p *Person) Greet() string {
return fmt.Sprintf("Hello, I'm %s", p.name)
}
// Interfaces
type Greetable interface {
Greet() string
}
// Embedding (composition)
type Student struct {
Person
school string
}
# Class definition
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
return f"Hello, I'm {self.name}"
# Instantiation
person = Person("John", 30)
# Inheritance
class Student(Person):
def __init__(self, name, age, school):
super().__init__(name, age)
self.school = school
def study(self):
return f"{self.name} is studying"
// Structs with methods
const Person = struct {
name: []const u8,
age: u32,
pub fn init(name: []const u8, age: u32) Person {
return Person{
.name = name,
.age = age,
};
}
pub fn greet(self: Person) []const u8 {
return "Hello, I'm " ++ self.name;
}
};
// Interfaces (using function pointers)
const Greetable = struct {
greet: fn (*const anyopaque) []const u8,
};
// Class definition
public class Person
{
private string name;
private int age;
public Person(string name, int age)
{
this.name = name;
this.age = age;
}
public virtual string Greet()
{
return $"Hello, I'm {name}";
}
}
// Instantiation
var person = new Person("John", 30);
// Inheritance
public class Student : Person
{
private string school;
public Student(string name, int age, string school)
: base(name, age)
{
this.school = school;
}
public override string Greet()
{
return base.Greet() + $" and I study at {school}";
}
}
// Class definition
class Person {
private:
std::string name;
int age;
public:
Person(const std::string& name, int age)
: name(name), age(age) {}
virtual std::string greet() const {
return "Hello, I'm " + name;
}
virtual ~Person() = default;
};
// Instantiation
Person person("John", 30);
// Inheritance
class Student : public Person {
private:
std::string school;
public:
Student(const std::string& name, int age,
const std::string& school)
: Person(name, age), school(school) {}
std::string greet() const override {
return Person::greet() + " and I study at " + school;
}
};
// Struct with function pointers (OOP-like)
typedef struct {
char name[50];
int age;
void (*greet)(struct Person*);
} Person;
void person_greet(Person* self) {
printf("Hello, I'm %s\n", self->name);
}
Person* person_new(const char* name, int age) {
Person* p = malloc(sizeof(Person));
strcpy(p->name, name);
p->age = age;
p->greet = person_greet;
return p;
}
// Class definition
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String greet() {
return "Hello, I'm " + name;
}
}
// Instantiation
Person person = new Person("John", 30);
// Inheritance
public class Student extends Person {
private String school;
public Student(String name, int age, String school) {
super(name, age);
this.school = school;
}
@Override
public String greet() {
return super.greet() + " and I study at " + school;
}
}
# Class definition
class Person
def initialize(name, age)
@name = name
@age = age
end
def greet
"Hello, I'm #{@name}"
end
end
# Instantiation
person = Person.new("John", 30)
# Inheritance
class Student < Person
def initialize(name, age, school)
super(name, age)
@school = school
end
def study
"#{@name} is studying"
end
end
// Class definition
class Person {
private var name: String
private var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
func greet() -> String {
"Hello, I'm \(name)"
}
}
// Instantiation
let person = Person(name: "John", age: 30)
// Inheritance
class Student: Person {
private var school: String
init(name: String, age: Int, school: String) {
self.school = school
super.init(name: name, age: age)
}
override func greet() -> String {
super.greet() + " and I study at \(school)"
}
}
Interfaces e Polimorfismo
- JavaScript
- PHP
- Rust
- Go
- Python
- Zig
- C#
- C++
- C
- Java
- Ruby
- Swift
// No native interfaces, use duck typing
class Dog {
makeSound() {
return "Woof!";
}
}
class Cat {
makeSound() {
return "Meow!";
}
}
// Polymorphism
function animalSound(animal) {
return animal.makeSound();
}
// TypeScript interfaces
interface Animal {
makeSound(): string;
}
<?php
// Interfaces
interface Animal {
public function makeSound(): string;
}
class Dog implements Animal {
public function makeSound(): string {
return "Woof!";
}
}
class Cat implements Animal {
public function makeSound(): string {
return "Meow!";
}
}
// Polymorphism
function animalSound(Animal $animal): string {
return $animal->makeSound();
}
// Traits (interfaces)
trait Animal {
fn make_sound(&self) -> String;
}
struct Dog;
impl Animal for Dog {
fn make_sound(&self) -> String {
"Woof!".to_string()
}
}
struct Cat;
impl Animal for Cat {
fn make_sound(&self) -> String {
"Meow!".to_string()
}
}
// Polymorphism
fn animal_sound(animal: &dyn Animal) -> String {
animal.make_sound()
}
// Interfaces
type Animal interface {
MakeSound() string
}
type Dog struct{}
func (d Dog) MakeSound() string {
return "Woof!"
}
type Cat struct{}
func (c Cat) MakeSound() string {
return "Meow!"
}
// Polymorphism
func AnimalSound(a Animal) string {
return a.MakeSound()
}
# Duck typing (no explicit interfaces)
class Dog:
def make_sound(self):
return "Woof!"
class Cat:
def make_sound(self):
return "Meow!"
# Polymorphism
def animal_sound(animal):
return animal.make_sound()
# ABC (Abstract Base Classes)
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def make_sound(self):
pass
// Function pointers (interface-like)
const Animal = struct {
make_sound: fn (*const anyopaque) []const u8,
};
const Dog = struct {
pub fn make_sound(self: *const Dog) []const u8 {
return "Woof!";
}
};
// Polymorphism through function pointers
fn animal_sound(animal: Animal) []const u8 {
return animal.make_sound(animal.self);
}
// Interfaces
public interface IAnimal
{
string MakeSound();
}
public class Dog : IAnimal
{
public string MakeSound() => "Woof!";
}
public class Cat : IAnimal
{
public string MakeSound() => "Meow!";
}
// Polymorphism
public static string AnimalSound(IAnimal animal)
{
return animal.MakeSound();
}
// Abstract classes
class Animal {
public:
virtual std::string makeSound() = 0;
virtual ~Animal() = default;
};
class Dog : public Animal {
public:
std::string makeSound() override {
return "Woof!";
}
};
class Cat : public Animal {
public:
std::string makeSound() override {
return "Meow!";
}
};
// Polymorphism
std::string animalSound(Animal* animal) {
return animal->makeSound();
}
// Function pointers in structs
typedef struct {
void* self;
char* (*makeSound)(void*);
} Animal;
char* dog_makeSound(void* self) {
return "Woof!";
}
char* cat_makeSound(void* self) {
return "Meow!";
}
// Polymorphism
char* animalSound(Animal* animal) {
return animal->makeSound(animal->self);
}
// Interfaces
public interface Animal {
String makeSound();
}
public class Dog implements Animal {
@Override
public String makeSound() {
return "Woof!";
}
}
public class Cat implements Animal {
@Override
public String makeSound() {
return "Meow!";
}
}
// Polymorphism
public static String animalSound(Animal animal) {
return animal.makeSound();
}
# Modules as interfaces
module Animal
def make_sound
raise NotImplementedError
end
end
class Dog
include Animal
def make_sound
"Woof!"
end
end
class Cat
include Animal
def make_sound
"Meow!"
end
end
# Polymorphism
def animal_sound(animal)
animal.make_sound
end
// Protocols (interfaces)
protocol Animal {
func makeSound() -> String
}
class Dog: Animal {
func makeSound() -> String {
"Woof!"
}
}
class Cat: Animal {
func makeSound() -> String {
"Meow!"
}
}
// Polymorphism
func animalSound(_ animal: Animal) -> String {
animal.makeSound()
}
Principais Conclusões
-
Modelos de herança — Java, C#, C++, PHP, Ruby, Swift e JavaScript usam herança simples baseada em classes com sintaxe
extendsou:; por exemplo,class Student extends Personem Java ouclass Student(Person)em Python. Go rejeita herança completamente e usa embedding:type Student struct { Person; school string }incorpora os campos e métodos de Person diretamente. Rust não tem herança alguma — apenas traits que os tipos implementam. Escolha Go ou Rust quando quiser composição ao invés de hierarquia; escolha Java/C#/Swift quando precisar de taxonomias de classe claras e sobrescrita de métodos. -
Padrões de interface — Java, C#, Swift e PHP exigem declarações explícitas de
implements:class Dog implements Animal. Go usa tipagem estrutural: qualquer tipo com um métodoMakeSound() stringsatisfaztype Animal interface { MakeSound() string }sem declará-lo. Python e Ruby dependem de duck typing — se temmake_sound(), funciona. As traits do Rust funcionam como interfaces:impl Animal for Dog { fn make_sound(&self) -> String { ... } }. C e Zig simulam interfaces via structs de ponteiros de função. Prefira interfaces implícitas estilo Go para flexibilidade; prefira interfaces explícitas quando quiser garantia de contrato em tempo de compilação. -
Filosofia de POO — POO tradicional (Java, C#, C++) é centrada em classes, hierarquias de herança e
virtual/overridepara polimorfismo. Go e Rust favorecem composição e traits: "prefira composição ao invés de herança." JavaScript e Python são multiparadigma — você pode usar classes ou evitá-las completamente. Se você está construindo modelos de domínio com hierarquias claras (ex.:Vehicle→Car→ElectricCar), Java/C#/Swift se destacam. Se quer designs planos e combináveis com cerimônia mínima, escolha Go ou Rust. -
Memória e ciclo de vida — C++ e Rust exigem atenção explícita ao ciclo de vida do objeto: C++ usa destrutores
virtuale RAII; o ownership do Rust previne referências pendentes. Java, C#, PHP, Ruby, Python e JavaScript usam coleta de lixo, então você raramente gerencia o tempo de vida do objeto. Go usa GC leve. Para programação de sistemas ou código crítico em performance, Rust e C++ dão controle; para desenvolvimento rápido, linguagens com coleta de lixo reduzem a carga cognitiva.