Executando verificação de segurança...
1

packages vs namespaces

Fala rapaziada, suave? Bom, ultimamente voltei a estudar java por motivos acadêmicos, e nesse retorno fui ver sobre packages e imports. E os achei, de certa forma, muito parecidos com os namespaces presentes no php. Com isso, fui explorar a aplicabilidade e funcionamento desses dois recursos, nessas duas respectivas linguagens.

Pra quem não conhece esse conceito ainda, segundo a w3schools, Namespaces são qualificadores que resolvem dois problemas diferentes:

  1. Eles permitem uma melhor organização agrupando classes que trabalham juntas para realizar uma tarefa
  2. Eles permitem que o mesmo nome seja usado para mais de uma classe

Como já havia estudado esse conceito, ao me deparar com os packages em java, pensei ser a mesma coisa, só que se apresentando de uma maneira distinta, visto as linguagens serem diferentes.

php:

<?php

namespace php\entities {

    class Person
    {
        function __construct(private string $name, private int $age)
        {
        }

        function getName(): string
        {
            return $this->name;
        }

        function setName(string $name): void
        {
            $this->name = $name;
        }

        function getAge(): int
        {
            return $this->name;
        }


        function setAge(int $age): void
        {
            $this->age = $age;
        }

        function __toString()
        {
            return <<<PERSON
                Person [
                    name={$this->name},
                    age={$this->age}
                ];
            PERSON;
        }
    }
}

No php, o uso de namespaces faz com que se assuma uma organização lógica de classes. Ou seja, essa organização, necessariamente, não diz respeito a estrutura de diretórios do seu projeto.

onde a classe localizada em raiz-project/resources/Class.php pode ter um namespace que seja diferente dessa estrutura.

Porém, no java não existe essa alternativa. Com o empacotamento seguindo, de certa forma, a estrutura de diretórios do projeto para que funcione.

java:

package com.galvao.mvn.studing.utils;

public class Person {

    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

E quando utilizo nomes distintos da estrutura de diretórios, ocorre esse aviso:

The declared package "studing.utils" does not match the expected package "com.galvao.mvn.studing.utils"Java(536871240)

Minhas dúvidas são:
São realmente o mesmo conceito de organização? Se sim, porque um permite o nome distinto e o outro não.

São conceitos distintos? Se sim, quais suas diferenças?

1

PHP não tem autoload por padrão

A diferença é que o PHP não carrega os arquivos das classes automaticamente por padrao.

Isso significa que ao fazer

use Foo\Bar\Classe;

new Classe();

O PHP não entende aonde vai encontrar aquele arquivo.

Autoload e PSR-4

Porém, existe um recuros "magico" chamado autoload (https://www.php.net/manual/pt_BR/language.oop5.autoload.php) aonde você pode definir uma função que será responsável por carregar o arquivo que contém as classes.

E ai é que entra o PSR-4, um padrao de autoloading amplamente utilizado, inclusive pelo Laravel, e implementado pelo composer por exemplo.

Nele, o namespace segue o mesmo caminho da pasta do arquivo:

namespace VendorName\PackageName\Foo\Bar;

class Classe {
}

por exemplo, quando usando o autoloader do composer, irá apontar para o arquivo:

vendor\VendorName\PackageName\Foo\Bar\Classe.php

aonde o primeiro vendor é algo específico do composer e não do PSR-4, pois é o diretório aonde o composer coloca os pacotes, para não misturar com o seu código.

Usando o autoloader padrão do composer, o código fica assim:

// obrigatoriamente você precisa carregar o autoloader do composer
// pois ele quem irá declarar a função de autoloader no PHP
require __DIR__ . '/vendor/autoload.php';

use VendorName\PackageName\Classe;

// por trás dos panos, o autoloader do composer irá executar um `require __DIR__ . '/vendor/VendorName/PackageName/Classe.php'
// e magicamente o codigo abaixo vai funcionar mesmo sem você ter requerido o arquivo manualmente 

new Classe();