Quando um recurso é considerado um “cidadão de primeira classe” em uma linguagem / plataforma de programação?

61

Eu já vi muitas vezes declarações como: "Por favor, faça deste recurso um cidadão de primeira classe em um e outro idioma / plataforma". Por exemplo, é dito sobre enumerações em C # / .net. Então, quando um recurso é considerado um "cidadão de primeira classe" em uma linguagem / plataforma de programação?

Gulshan
fonte

Respostas:

40

Definição

Um objeto é de primeira classe quando:

  • pode ser armazenado em variáveis ​​e estruturas de dados
  • pode ser passado como um parâmetro para uma sub-rotina
  • pode ser retornado como resultado de uma sub-rotina
  • pode ser construído em tempo de execução
  • possui identidade intrínseca (independente de qualquer nome)

O termo "objeto" é usado livremente aqui, não necessariamente se referindo a objetos na programação orientada a objetos. Os tipos de dados escalares mais simples, como números inteiros e de ponto flutuante, são quase sempre de primeira classe.

http://en.wikipedia.org/wiki/First_class_object

Waquo
fonte
1
Então, o que faz enumerações de objetos de segunda classe em .net / C #?
precisa saber é o seguinte
7
@ Gulshan - você poderia argumentar sobre a falta de identidade intrínseca - as enumerações C # são basicamente apenas açúcar sintático (ou seja, um "nome dado") para um valor inteiro. Compare com Java, onde as enumerações são objetos por si só.
Mkera
@mikera, no .NET enums são valores por si só. Java simplesmente não possui valores, apenas objetos, essa é a única diferença.
SK-logic
@mikera: Embora isso impeça as enumerações de Java de ter algumas boas propriedades, como poder representar campos de bits com elas. Embora sua implementação seja provavelmente mais de primeira classe, a maioria de suas APIs ainda possui muitas constantes de número inteiro (ou string) e muitos usos dessas não podem ser facilmente substituídos por enumerações.
Joey
Eu não acho que enums podem ser construídas em tempo de execução em .Net, podem? Eu pensei que eles eram sempre constantes.
travis
33

A noção de "cidadão de primeira classe" ou "elemento de primeira classe" em uma linguagem de programação foi introduzida pelo cientista de computação britânico Christopher Strachey na década de 1960, no contexto de funções de primeira classe. A formulação mais famosa desse princípio está provavelmente em Estrutura e interpretação de programas de computador por Gerald Jay Sussman e Harry Abelson:

  • Eles podem ser nomeados por variáveis.
  • Eles podem ser passados ​​como argumentos para procedimentos.
  • Eles podem ser retornados como resultados dos procedimentos.
  • Eles podem ser incluídos nas estruturas de dados.

Basicamente, isso significa que você pode fazer com esse elemento da linguagem de programação tudo o que você pode fazer com todos os outros elementos na linguagem de programação.

É tudo sobre "direitos iguais": você pode fazer tudo o que precede, com, digamos, números inteiros. Por que outra coisa deveria ser diferente?

A definição acima é um pouco restritiva, no sentido de que realmente fala apenas sobre o aspecto de primeira classe relacionado a ser objeto do programa. Uma definição mais geral seria que uma coisa é de primeira classe, se você pode fazer tudo com ela, também pode fazer com outras coisas de tipo semelhante.

Por exemplo, operadores e métodos Java são de tipo semelhante. Você pode definir novos métodos, pode (um pouco) escolher livremente os nomes de seus próprios métodos, pode substituir métodos, pode sobrecarregar métodos. James Gosling também pode fazer tudo isso com os operadores, mas você e eu não podemos. Quer dizer, ao contrário da crença popular, Java faz sobrecarga de operadores de apoio: por exemplo, o +operador é sobrecarregado para byte, short, int, long, float, doublee String, e IIRC em Java 7 também para BigIntegere BigDecimal(e provavelmente um casal I esqueceu), é só que vocênão tem nenhuma influência sobre isso. Isso claramente torna os operadores de segunda classe, de acordo com esta segunda definição. Observe que os métodos ainda não são objetos de primeira classe, de acordo com a primeira definição. (Isso torna os operadores de terceira classe?)

Jörg W Mittag
fonte
6

Geralmente, isso se refere a uma construção passável como parâmetro, pode ser definida como um tipo de retorno de uma função ou pode ser atribuído um valor. Normalmente você precisa construí-los em tempo de execução. Por exemplo, uma instância de uma classe seria um cidadão de primeira classe em c ++ ou java, mas uma função em C não seria.

Pemdas
fonte
O que faz de uma classe um cidadão de primeira classe em c ++?
Bjarke Freund-Hansen
2
@ bjarkef: Parece que isso já foi respondido por corresponder à descrição oferecida nas frases anteriores.
doppelgreener
@ Jonathan: Sim, desculpe, eu li errado o "construí-los em tempo de execução". Sim, você pode construir uma instância de uma classe em tempo de execução (um objeto), mas não a própria classe. Foi isso que me confundiu.
Bjarke Freund-Hansen
1
Passar por parâmetro ainda não é suficiente. Em C / C ++, eu ainda consideraria as funções como cidadãos de segunda classe. Eles podem ser passados ​​como parâmetros, retornados como resultados colocados dentro de outros objetos. Mas eles não podem ser manipulados sem a ajuda de outras construções (como std :: bind é necessário para ligar parâmetros a uma função).
Martin York
@ Martin Eu nunca disse que as funções eram cidadãos de primeira classe em C / C ++.
Pemdas
1

Eu diria que um recurso é um cidadão de primeira classe se for implementado apenas pelo idioma.
isto é, não requer recursos de vários idiomas ou uma biblioteca padrão para implementar esse recurso.

Exemplo:

Em C / C ++, não considero funções um cidadão de primeira classe (outros podem).
Isso ocorre porque existem maneiras de manipular funções que são suportadas diretamente pelo idioma, mas exigem o uso de outros recursos do idioma. A ligação de parâmetros a uma função não é diretamente suportada e você deve criar um functor para implementar esse recurso.

Martin York
fonte
1
Isso não tornaria as funções vinculadas (ou "fechamentos") de primeira classe, enquanto as próprias funções são? Como o suporte do 0x para fechamentos influencia sua análise?
precisa saber é o seguinte
@ Nurk Fred: Tudo depende do idioma. Em alguns idiomas, os fechamentos são sistemas de primeira classe. Em outros não. Ainda não estou familiarizado com o C ++ 0x para fazer um comentário explícito.
Martin York
Digamos que a linguagem seja C ou C ++ (mas não 0x), como você responde. Sua definição de "primeira classe" não tornaria as funções vinculadas (ou "encerramentos") de primeira classe, enquanto as funções em si são?
precisa saber é o seguinte
@ Nurk Frred: Se você limitar a única coisa que você pode fazer com uma função é torná-los um fechamento, então com certeza. Mas, para mim, é como dizer se a sua plataforma suporta adição de números inteiros apenas importando uma biblioteca. Então os números inteiros são cidadãos de primeira classe, mas a adição de números inteiros não é considerada. Na minha opinião, o fechamento é uma operação que pode ser executada em uma função que efetivamente retorna uma nova função (mas depende de como você a define). Mas fechamento e vinculação são apenas duas operações, quantas outras estamos excluindo da discussão (não tenho certeza de que tenha sido uma pergunta).
Martin York
@ Martin: Eu não devo estar me explicando claramente. Dado que "um recurso é um cidadão de primeira classe se for implementado apenas pelo idioma", as funções em C e C ++ são implementadas apenas pelo idioma e, portanto, seriam de primeira classe. Funções limitadas (que também podem ser chamadas de "fechamentos") são o que você está falando com parâmetros de ligação, etc., mas esse é um recurso diferente.
precisa saber é o seguinte
-1

Para adicionar um exemplo às respostas já fornecidas:

No WCF / C #, você atualmente precisa marcar um objeto de classe com um atributo de contrato de serviço para que ele funcione como um serviço. Não existe tal coisa como:

public **service** MyService (in relation public **class** MyClass). 

Uma classe é um cidadão de primeira classe em c #, onde um serviço não é.

Espero que isto ajude

Syg
fonte