Czy programowanie obiektowe jest takie samo w każdym języku programowania?

0

Czy programowanie obiektowe jest takie samo w każdym języku programowania? Czy jeżeli nauczę się wszystkiego o programowaniu obiektowym to zdobytą teorię będę mógł z łatwością wykorzystać w dowolnym języku?

3

Zależy co przez to rozumiesz. Jeśli chodzi o idee stojące za OOP i jak pisać dobry kod, to mniej więcej tak. Jeśli jednak sądzisz, że nauczenie jednego języka obiektowego "magicznie" nauczy Cię innego, to nie. Ważną rzeczą jest by pamiętać, że nawet w językach nieobiektowych (jak C) można pisać obiektowo.

0

Chodzi mi o to czy są znaczące różnice w działaniu pewnych funkcjonalności pomiędzy językami np klasy tworzy się za pomocą słowa class, klasa musi mieć konstruktor itp. A nie że np w jakimś języku nie ma konstruktorów i klasy tworzy się jakoś inaczej. Ciężko jest mi sprecyzować co dokładnie mam na myśli bo bardziej chodzi o ogólne podejście.

0

Hej,
wiele zależy od języka. Każdy język ma swoją specyfikę programowania obiektowego, o ile w nim da się tak programować. Na przykład w Rubym wszystko jest obiektem. W VBA pod Excelem na przykład wykorzystujemy obiekty zdefiniowane i stworzone przez twórcę Excela (komórki, arkusze, i inne obiekty)...

0

W Python i Ruby wszystko jest obiektem, w Javie nie do końca.

0

Idee pewnie i są mniej więcej jednakowe, jednak każdy język czymś się wyróżnia, więc nie wystarczy nauczyć się jednego. Każdy język przede wszystkim ma inną składnię, różnice istnieją też w funkcjonalności klas (np. liczba poziomów dostępu do składowych i sposoby dostępu do nich), ale też jeśli chodzi o takie niuanse jak wielodziedziczenie (jedne języki wspierają, inne nie).

Różnic jest tak dużo, że programowanie obiektowe jest zupełnie inne w każdym języku programowania. Jedne różnią się bardziej, inne mniej, mimo wszystko każdego trzeba się uczyć z osobna.

0
Programowanie Obiektowe napisał(a):

Chodzi mi o to czy są znaczące różnice w działaniu pewnych funkcjonalności pomiędzy językami np klasy tworzy się za pomocą słowa class, klasa musi mieć konstruktor itp. A nie że np w jakimś języku nie ma konstruktorów i klasy tworzy się jakoś inaczej.

Istnieją takie języki obiektowe, w których klas się nie tworzy, bo ich nawet nie ma.

4

Przykłady obiektowe w różnych językach:

Java [uruchom]

interface Hello {
    void hello();
}

class World implements Hello {
    public void hello() { System.out.println("Hello, World!"); }
}

class Greeter implements Hello {
    private String name;

    Greeter(String name) { this.name = name; }

    public void hello() { System.out.println("Hello," + this.name + "!"); }
}

class Main {
    public static void main(String[] args) {
        Hello world = new World();
        Hello greeter = new Greeter("Programowanie Obiektowe");

        world.hello();
        greeter.hello();
    }
}

C [uruchom]

#include <stdio.h>

#define implements struct

typedef struct Hello {
    void (*hello)(void*);
} Hello;

struct World {
    implements Hello super;
};

void World_hello(void* this) { puts("Hello, World!"); }

Hello* newWorld() {
    struct World* world = (struct World*)malloc(sizeof(struct World));
    world->super.hello = *World_hello;

    return (Hello*)world;
}

struct Greeter {
    implements Hello super;
    char name[255];
};

void Greeter_hello(void* this) { printf("Hello, %s!\n", ((struct Greeter*)this)->name); }

Hello* newGreeter(char* name) {
    struct Greeter* greeter = (struct Greeter*)malloc(sizeof(struct Greeter));
    greeter->super.hello = *Greeter_hello;
    strncpy(greeter->name, name, 254);

    return (Hello*)greeter;
}

void hello(Hello* object) {
    object->hello(object);
}

int main() {
    Hello* world = newWorld();
    Hello* greeter = newGreeter("Programowanie Obiektowe");

    hello(world);
    hello(greeter);
    
    free(world);
    free(greeter);
    
    return 0;
}

Jakby ktoś się zastanawiał kto tak pisze, to zastanówcie się jak jest zaimplementowany dostęp do plików w *niksach, gdzie ten sam interfejs odpowiada za pliki, sockety, pipes, block devices, etc.

Elixir (procesy) [uruchom]

defmodule World do
  use GenServer

  def start, do: GenServer.start(__MODULE__, nil)

  def init(_), do: {:ok, nil}

  def handle_call(:hello, _from, state) do
    IO.puts("Hello World!")

    {:reply, nil, state}
  end
end

defmodule Greeter do
  use GenServer

  def start(name) when is_binary(name), do: GenServer.start(__MODULE__, name)

  def init(name), do: {:ok, name}

  def handle_call(:hello, _from, state) do
    IO.puts("Hello " <> state <> "!")

    {:reply, nil, state}
  end
end

{:ok, world} = World.start()
{:ok, greeter} = Greeter.start("Programowanie Obiektowe")

GenServer.call(world, :hello)
GenServer.call(greeter, :hello)

Można by tutaj użyć również protokołów, ale IMHO byłoby to oszustwo, bo nie można tego bezpośrednio przełożyć 1:1 na Erlanga. Już behaviours byłyby bliższe, ale dalej "najbardziej obiektowe" rozwiązanie to to.

JS

Ze słowem kluczowym new (old style) [uruchom]

function World() {}
World.prototype.hello = function () { console.log("Hello World") }

function Greeter(name) { this.name = name }
Greeter.prototype.hello = function () { console.log("Hello " + this.name + "!") }

var world = new World()
var greeter = new Greeter("Programowanie Obiektowe")

world.hello()
greeter.hello()

Przy użyciu domknięć [uruchom]

function World() {
  return {
    hello: function() { console.log("Hello World!") }
  }
}

function Greeter(name) {
  return {
    hello: function() { console.log("Hello " + name + "!") }
  }
}

var world = World()
var greeter = Greeter("Programowanie Obiektowe")

world.hello()
greeter.hello()

Używając nowego class [uruchom]

class World {
  hello() { console.log("Hello, World!") }
}

class Greeter {
  constructor(name) { this.name = name }

  hello() { console.log(`Hello ${this.name}!`) }
}

const world = new World()
const greeter = new Greeter("Programowanie Obiektowe")

world.hello()
greeter.hello()

Rust [uruchom]

trait Hello {
  fn hello(&self);
}

struct World;

impl Hello for World {
    fn hello(&self) { println!("Hello World!") }
}

struct Greeter<'a>(&'a str);

impl<'a> Hello for Greeter<'a> {
    fn hello(&self) { println!("Hello, {}!", self.0) }
}

fn static_dispatch<T: Hello>(val: T) { val.hello() }

fn dynamic_dispatch(val: Box<dyn Hello>) { val.hello() }

fn main() {
    println!("Static dispatch");
    static_dispatch(World);
    static_dispatch(Greeter("Programowanie Obiektowe"));

    println!("\nDynamic dispatch");
    dynamic_dispatch(Box::new(World));
    dynamic_dispatch(Box::new(Greeter("Programowanie Obiektowe")));
}

Tutaj są 2 rozwiązania, bo Rust tak samo jak C++ pozwala zarówno na statyczny dispatching (w czasie kompilacji jest definiowana wersja, która zostanie odpalona) oraz dynamiczny (w czasie wykonywania programu jest używana vtable do określenia jaka funkcja zostanie odpalona).

Go [uruchom]

package main

import (
	"fmt"
)

type Hello interface {
	hello()
}

type World struct{}

func (_ World) hello() {
	fmt.Println("Hello, World!")
}

type Greeter struct {
	name string
}

func (greeter Greeter) hello() {
	fmt.Println("Hello,", greeter.name, "!")
}

func hello(val Hello) {
	val.hello()
}

func main() {
	hello(World{})
	hello(Greeter{name: "Programowanie Obiektowe"})
}
0

Uzupełnię trochę przedmówcę, jeśli chodzi o przykład w Go, bo nie pojawiło się embedowanie struktów, które "symuluuje" dziedziczenie - raczej się zwykle tego tak nie pisze (a używa interfejsów jak @hauleth pokazał), ale możliwość istnieje.

Tu można uruchomić w Go Playground:

package main

import (
	"fmt"
)

type (
	// Struktura, która "rozszerza" inne
	CarType struct {
		name   string
		wheels int
	}

	DieselEngine struct {
		engineType string
		euroNorm   int
		fuel       string
	}

	EngineType struct {
		enginePower int
		DieselEngine
	}

	// Struktura główna
	Car struct {
		model string
		color string
		CarType
		EngineType
	}
)

func main() {
	Fiat := &Car{
		model: "bravo",
		color: "red",
		CarType: CarType{
			name:   "civil",
			wheels: 4,
		},
		EngineType: EngineType{
			enginePower: 100,
			DieselEngine: DieselEngine{
				engineType: "diesel",
				euroNorm:   4,
				fuel:       "oil",
			},
		},
	}

	fmt.Println("Model: ", Fiat.model)
	fmt.Println("Color: ", Fiat.color)
    // Poniższe pola już są "dziedziczone", ale odwołujemy się normalnie
	fmt.Println("Type: ", Fiat.name)
	fmt.Println("Wheels: ", Fiat.wheels)
	fmt.Println("Engine type: ", Fiat.engineType)
	fmt.Println("Engine power: ", Fiat.enginePower)
	fmt.Println("Engine type: ", Fiat.euroNorm)
	fmt.Println("What you need to power the engine: ", Fiat.fuel)
}
0
hauleth napisał(a):

Przykłady obiektowe w różnych językach:

Java [uruchom]

interface Hello {
    void hello();
}

class World implements Hello {
    public void hello() { System.out.println("Hello, World!"); }
}

class Greeter implements Hello {
    private String name;

    Greeter(String name) { this.name = name; }

    public void hello() { System.out.println("Hello," + this.name + "!"); }
}

class Main {
    public static void main(String[] args) {
        Hello world = new World();
        Hello greeter = new Greeter("Programowanie Obiektowe");

        world.hello();
        greeter.hello();
    }
}

S3 [uruchom]

hello <- function(x, ...) {
  UseMethod("hello", x)
}

hello.World <- function(x, ...) {
  "Hello, World!"
}

hello.Greeter <- function(x, ...) {
  paste0("Hello ", x, " !")
}

world <- "Magdo Madziu Magdaleno"
class(world) <- "World"

greeter <- "Programowanie Obiektowe"
class(greeter) <- "Greeter"

hello(greeter)
hello(world)

S4 [uruchom]

setClass("Greeter", representation(name = "character"))
setClass("World", representation(name = "character")) # muszę dodać name, bo inaczej klasa będzie wirtualną

greeter <- new("Greeter", name = "Programowanie Obiektowe")
world <- new("World")

hello <- function(x) 0
setGeneric("hello")

setMethod("hello", signature("Greeter"), function(x) {
  paste0("Hello ", x@name, " !")
})

setMethod("hello", signature("World"), function(x) {
  "Hello, World!"
})

hello(world)
hello(greeter)

RC [uruchom]

Przy Reference Class połamałem klawiaturę, więc zrobię kaszanę byle wynik był ok:

Hello <- setRefClass("Hello", 
                     fields = list(name = "character"),
                     methods = list(hello = function(x) {
                       paste0("Hello ", name, " !")
                     }))

World <- Hello$new(name = "World")
Greeter <- Hello$new(name = "Programowanie Obiektowe")
World$hello()
Greeter$hello()

1 użytkowników online, w tym zalogowanych: 0, gości: 1