Oque são classes em POO?

Em java a explicação mais comum sobre classes que encontro é algo parecido: "ah, uma classe é um modelo para um objeto, como se fosse um molde", tudo bem, mas o problema é o seguinte: e uma classe sem atributos, apenas com métodos? mudando um pouco o rumo, em JS o elemento similar se chama módulo, ele é um pedaço do codigo onde podemos acoplar em qualquer outra parte do programa, eu sei que o conceito é o mesmo, mas nunca me desceu muito bem essa explicassão que uma classe é um modelo para um objeto, alguem poderia explicar melhor oque é uma classe?

Idealmente, existe essa ideia de que "classe é o molde (ou a receita, ou a planta da casa), e a instância é o objeto em si (ou o bolo, ou a casa propriamente dita)". Neste caso, os campos (que não é a mesma coisa que atributo) seriam uma forma de guardar o estado do objeto (informações que determinam o valor daquela instância, a grosso modo). E os métodos são formas de se manipular o objeto, ou obter informações dele.

Mas nada impede que se tenha apenas métodos. Isso é comum em classes utilitárias, cujo objetivo é "fazer algo", sem depender do estado interno. Um exemplo que tem no Java é a classe Math, que só possui métodos estáticos. Afinal, para arredondar um número para baixo não precisa de variáveis de instância para guardar o estado interno do objeto Math. O método Math.floor só faz o cálculo e pronto. Por que precisaria de m = new Math() para depois chamar m.floor, sendo que o método floor faz todo o trabalho, sem precisar de nenhuma variável de instância?

Isso é por causa da limitação regra da linguagem que diz que tudo precisa estar dentro de uma classe. Não pode ter uma função "solta" ou em módulos, que nem no JavaScript, por exemplo. Daí que muitas vezes a classe só está lá para cumprir esta "burocracia" da linguagem.

E nem vou mencionar que muitas vezes as pessoas programam em Java de forma procedural. O fato do código estar em uma classe não garante que ele será orientado a objeto.

Obs: nas versões mais novas é possível rodar um programa sem criar uma classe explicitamente, mas não se engane, pois internamente ainda é criada uma classe.


E vale lembrar - como eu já disse aqui e aqui - que não existe uma definição única, canônica e universal sobre Orientação a Objetos (sugiro que leia esses links, e também os outros links que estão lá). Mas só pra resumir:

  • existem várias "escolas"/vertentes de orientação a objeto (uma delas se tornou a mais comum, e muita gente acha que é a única, ou a "certa")
  • usar classes não é a única forma de se obter um código OO (independente da vertente escolhida). JavaScript, por exemplo, usa protótipos (até existe a palavra-chave class, mas ela é um syntatic sugar)

Ou seja, existe a definição "clássica" de classe: o molde a partir do qual serão criadas as instâncias. Mas dependendo da linguagem, este conceito pode acabar sendo subvertido. No caso do Java, como tudo precisa estar dentro de uma classe, os módulos (muito comuns em outras linguagens) acabam sendo emulados como classes utilitárias, que geralmente só possuem métodos estáticos e nem dá para criar uma instância (muitas têm o construtor privado - não tem como fazer new Math() por exemplo).

Quanto mais leio, mais observo que os cursos abstraem demais conceitos importantes e deixam iniciantes como eu cheio de buracos de conhecimento, acho engraçado como em JS o modulo "existe por si so" e se chama ele, diferente de java onde voce precisa criar uma instancia

Uma classe mesmo sem atributos continua sendo um molde para objetos. Quando falamos em instância de uma certa classe estamos falando da realização das especificações definadas (na classe) ocupando um lugar na memória. Uma classe sem atributos ela terá comportamento que são os métodos e cada objeto instanciado terá um lugar na memória de forma isolada existindo.

Nossaaa, sua explicação me fez refletir muito sobre o assunto, espero chegar a esse nivel de clareza logo na hora de criar um código, se eu entendi bem: só o ato de chamar um método e armazena-lo dentro de uma variável já é uma forma de instanciar um obj, a forma de explicar por ai me fez entender que uma instancia só é instancia quando temos a palavra new, como por exemplo: Pessoa fulano = new Pessoa();
Quase sempre será isso mesmo, para se ter uma instância de um objeto você usa o `new`. Isso pode variar de uma linguagem para outra, mas normalmente segue o mesmo padrão. É um exemplo muito raso, mas você pode pensar em classes como _plantas para construção de uma casa_, a casa construída é uma _"instância da planta"_. A mesma planta pode ser usada para quantas casas forem possíveis, mas cada casa construída oculpa um espaço com seu devido endereço, o que acontece com uma não interfere na outra.
Exatamente - quando você realiza um objeto você tem o que chamamos de instância. Uma classe por si não tem como residir em vários lugares na memória de forma isolada.

Olá, tudo bem?

Esta é uma pergunta interessante, e gostaria de colaborar com uma provocação. Eu gosto de uma abordagem mais "poética". Não que eu acredite que ela seja mais ou menos correta, mas pode ajudar a compor uma boa definição de classe quando estiver escrevendo seus códigos (pelo menos me ajuda).

Eu vou pular toda a chatice sobre os 4 conceitos básicos de POO porque certamente você já viu sobre isso, e é fácil de encontrar pela web.

A classe representaria um contexto, e sua principal função é não só defini-lo, mas também protegê-lo.

Quando você faz uma classe chamada Pessoa, você deve pensar o que importa pro seu contexto. Geralmente pensamos em nome, altura, peso, etc. A questão é: para um sistema médico, a definição de uma pessoa pode ser diferente do que para um sistema veterinário. Para este último, seu peso, altura, tipo sanguíneo, nome de mãe e pai, alergia à medicamentos, entre outros, realmente não importa. Isto quer dizer que modelagem em POO não é sobre o mundo como ele é, mas sob a ótica e o viés do contexto que você está analisando/desenvolvendo.

Os objetos são o que? Se responder instância de uma classe, a pergunta muda para "e o que é uma instância?". Então é uma resposta um tanto pobre, eu diria. Acredito que são a individualização do contexto. Todos somos pessoas, mas certamente não somos iguais. O objeto é a definição de um elemento, com atributos que fazem sentido para aquele contexto, e que permitem diferenciar uns dos outros. Logo, eu sou eu porque meu atributos são diferentes dos seus, mesmo não deixando de ser pessoas. Podemos viajar um pouco mais aqui e falar sobre gêmeos identicos (que possuem atributos iguais mas certamente são pessoas diferentes), mas até isso vale, pois na maioria das linguagens que trabalham com POO dois objetos iguais não significa que são os mesmos objetos.

Aí vem sua colocação: e os métodos? O que são e porque faria sentido uma classe só de métodos?

Os métodos são algoritmos. Algoritmo é uma sequência de ações para alcançar um estado, objetivo, ou qualquer outro termo que te deixe confortável. Isto nos leva a pensar que um método seria "como realizar algo dentro de um contexto". E muitas vezes, um indivíduo fazendo algo tem resultado diferente de outro indivíduo, no mesmo contexto, fazendo a mesma coisa. Por exemplo, suponha que exista o método gritarProprioCPF na nossa classe Pessoa (não me pergunte o porquê). Dois indivíduos diferentes teriam resultados diferentes. Isto porque este é um método que depende diretamente de um dos atributos do indivíduo que está gritando, apesar do algoritmo ser o mesmo para todos:

  • Lembrar do CPF
  • Encher os pulmões
  • Abrir a boca
  • Gritar

É por isto que os métodos são definidos nas classes, mas executados através do objeto, para que fique claro os atributos de contexto que devem ser levados em consideração durante a execução.

Também explica um pouco dos puristas de POO reclamarem de JS e Pyhton, pois por padrão você pode "injetar" funções diretamente nos objetos, independente da definição de classe, e muitas vezes isto acaba se assemelhando a métodos.

Agora, existem algoritmos que não dependem de nenhum atributo do indivíduo, e o resultado é exatamente igual para todos eles, por exemplo jogarOvoNoChao. A questão é: que ovo? O que eu te der, claro! Logo, sendo mais completo, teriamos public OvoQuebrado jogarOvoNoChao(OvoDeGalinha ovo). Então perceba que os parâmetros definem atributos a serem considerados no algoritmo e que não estão contidos no próprio indivíduo daquele contexto, devem ser recebidos de fora dele. Considerando o mesmo ovo, tanto faz eu ou você (ou qualquer objeto da classe Pessoa) jogar ele no chão, o resultado será o mesmo. Isto é o que chamamos de um método estático, independe do objeto, mas ainda faz parte do contexto, e por isso são definidos na classe.

No Python existe ainda um terceiro "tipo" de método, o método de classe. De forma extremamente resumida e simplificada, apesar de ser acessado pelo objeto, é um método que o this armazena a classe ao invés do próprio objeto.

E existem coisas que não fazem muito sentido individualizar. Como o colega kht exemplificou, a matemática é um contexto único, individualizável. Não existem atributos que possam diferenciar uma matemática de outra. E ela define uma série de algoritmos: soma, divisão, derivação e etc. Todos eles são bem definidos, mas dependem de valores que devem ser fornecidos externamente (parâmetros). Portanto, poderiamos dizer que esta seria uma classe formada totalmente e apenas de métodos estáticos. E se não vamos individualizar, porque se preocupar em instanciar então? Para o Python, módulos são literalmente objetos de uma classe, e sua instanciação ocorre na importação dele.

Por último, existe o aspecto de proteção que citei inicialmente.

Eu não posso chegar e simplesmente mudar seu CPF. O nosso consultório poderia ficar com uma série de registros médicos falando sobre um indivíduo que já não é mais você. Teríamos então uma situação problemática, e há duas soluções: não permitir que CPF mudem, ou anotar em algum lugar (talvez no próprio registro) que seu CPF mudou para X. Então, em POO, um método se responsabiliza em proteger a integridade do contexto e de seus indivíduos, não permitindo idades negativas, pessoas sem nomes e propagando alterações importantes a outros pontos do código que possa interessar. É por isso dos benditos "getters/setters", bastante populares no Java. É uma forma de restringir acesso direto ao atributo e controlar tanto o acesso quanto a edição deste.

Bom, acredito que seja isto, espero que ter ajudado. Bons estudos!

Eu penso que classe é uma forminha para gerar objetos, tipo uma forminha de gelo. Você possui atributos que o objeto terá (formato, tamanho) e métodos (encher, esvaziar, solidificar). Essa classe forma diversos objetos iguais ou não. Você poderia criar essa classe sem os atributos que não teria nenhum problema. Já o módulo, é realmente só um módulo. É uma forma de desacoplar o código e separar em outros arquivos para reutilizar em outras ocasiões. Não tem funcionamento similar com uma classe, ele está mais para uma função.