Existem idiomas OO sem herança?

22

Durante uma revisão de código hoje, um colega meu disse algo interessante:

prototypesó é útil quando você precisa de herança - e quando a herança é uma boa ideia ?

Pensei sobre isso e percebi que geralmente uso herança para contornar códigos mal projetados em primeiro lugar. O estilo OO moderno prefere composição a herança, mas não conheço nenhum idioma que tenha levado isso a sério e que realmente a imponha .

Existem linguagens de programação de uso geral com classes, objetos, métodos, interfaces e assim por diante, que não permitem a herança baseada em classe? (Se essa ideia não faz sentido, por que não?)

Benjamin Hodgson
fonte
7
Seu colega o desviou. Também prototypeé útil para quando você possui métodos e propriedades públicos que devem ser compartilhados entre instâncias. Também é útil porque permite que você use corretamente o instanceofoperador em JavaScript: if (foo instanceof Foo) { ....
Greg Burghardt
2
Acho que devemos fazer uma distinção entre a herança de tipo, estado e comportamento. A preferência de composição é muito comum na comunidade Java, mas, ao mesmo tempo, a herança (e até a herança múltipla) de tipos é amplamente usada e incentivada ... e realizada usando a implementspalavra - chave e interfaces (em oposição à herança de estado e comportamento introduzido com o uso da extendspalavra-chave em classes contendo qualquer implementação).
toniedzwiedz
6
Preferir composição não significa abandonar completamente a herança é uma boa ideia.
Caleb
5
veja Java sem a herança de implementação : "go do Google é um exemplo de uma linguagem que acaba com a herança de implementação ao ser OOP ..."
mosquito
1
@GregBurghardt O mesmo pode ser realizado com uma função de fábrica que retorna um objeto contendo funções (armazenando dados privados no fechamento). new, thisE prototypesão todos muito de um campo minado para uso comum IMO.
Benjamin Hodgson

Respostas:

18

Deixando de lado a questão da definição de programação orientada a objetos, a questão se torna uma das "existem linguagens que usam apenas composição e não possuem ferramentas para herança?"

A resposta para isso é simplesmente "sim". Além disso, não há como fazer a herança como alguém pensa nela. Um pode incorporado um objecto noutro objecto e a estender esse objecto. Da linguagem desorientada a objetos ( espelho do github ):

type Person struct {
        Name string
}

func (p *Person) Intro() string {
        return p.Name
}

type Woman struct {
        Person
}

func (w *Woman) Intro() string {
        return "Mrs. " + w.Person.Intro()
}

Você tem uma estrutura de pessoa que tem um Nome que é uma String. Tem uma função pública chamada Intro que retorna o nome. A estrutura Woman também tem uma função para Intro, que acessa o suporte incorporado nela. E assim, podemos cumprir as intenções de herança usando apenas composição.

Mais sobre isso pode ser visto em Tutoriais do GoLang: Herança e subclassificação no Go - ou em sua quase semelhança .

Então, sim, é possível ter uma linguagem OO sem herança, e uma existe.

Dentro de casa, isso é conhecido como incorporação e oferece às estruturas anexas a capacidade de acessar os campos e funções incorporados como se os tivessem também - mas não é uma subclasse. A filosofia de design pode ser encontrada nas Perguntas frequentes sobre Go: Por que não há herança de tipo?


fonte
Também se poderia comentar sobre o uso de typedefe structno C ...
cwallenpoole
@cwallenpoole, de fato, existem idéias semelhantes, embora eu hesite em chamar C de linguagem orientada a objetos.
Não sei. Admito que você não pode criar objetos com funções anexadas funciona contra ele, mas sem herança, o OOP perde muito do seu sabor.
precisa saber é o seguinte
@cwallenpoole e começamos a definir o que é herança e orientação a objetos. Mas é possível, é apenas uma maneira diferente de pensar sobre o problema. O fato é que a herança é a maneira como a maioria dos programadores de C ++ e Java pensa em extensão ... mas existem outros modelos. Extensão sem herança: 1 , 2 , 3 são boas leituras.
O link para "Linguagem Desorientada a Objetos" está preso em um loop de redirecionamento no momento, mas encontrei o artigo aqui: github.com/nu7hatch/areyoufuckingcoding.me/blob/master/content/… . Obrigado!
Matt Brown
7

Existem linguagens de programação de uso geral com classes, objetos, métodos, interfaces e assim por diante, que não permitem a herança baseada em classe?

Isso se parece muito com uma descrição do VBA - Visual Basic for Applications, incorporado no Microsoft Office e outros hosts habilitados para VBA (por exemplo, AutoCAD, Sage 300 ERP, etc.) ou mesmo VB6. O "A" de "Básico" significa "Para todos os fins" de qualquer maneira, então há a parte "de uso geral".

O VB6 / VBA possui classes (e, portanto, objetos), métodos e interfaces - você pode definir uma ISomethinginterface em um módulo de classe como este:

Option Explicit

Public Sub DoSomething()
End Sub

E depois tem outra classe que faz isso:

Option Explicit
Implements ISomething

Private Sub ISomething_DoSomething()
    'implementation here
End Sub

Essa classe, expondo nenhum membro público, só poderia ser acessada por meio de sua ISomethinginterface - e poderia haver dezenas de implementações diferentes ISomethingpor aí, então o código OOP VBA é perfeitamente capaz de polimorfismo e é perfeitamente legal para uma determinada classe para implementar várias interfaces também.

No entanto, o VB6 / VBA não permite a herança de classe ; portanto, você não pode herdar uma implementação de outro tipo, apenas sua interface. Agora, se isso é um acidente, uma falha de design, um golpe de gênio ou uma enorme e feia supervisão estão abertos a debate; não está claro se o VB6 / VBA leva isso a sério , mas definitivamente o aplica .

Se o Go não faz herança de classe e ainda assim é uma linguagem OOP , não vejo por que o VB6 / VBA também não poderia ser considerado uma linguagem OOP.</PreemptiveResponseToVBAHatersThatWillSayItIsNotAnOOPLanguage>

Mathieu Guindon
fonte
1
Para ser justo, o OP perguntou sobre as línguas modernas . =;) -
RubberDuck
@RubberDuck #burn!
Mathieu Guindon
0

Você pode fazer com que o compilador imponha herança seletiva por meio do uso de privado / protegido e pelo uso moderno das técnicas "PImpl" ou "Implementação Privada".

Muitas APIs expõem apenas os componentes que você deseja que um usuário herde e ocultam o restante em uma classe de implementação separada. Portanto, você pode escrever classes cujas interfaces públicas são, de fato, não herdáveis, apenas utilizáveis ​​através da composição de objetos e aplicadas pelo compilador. Isso geralmente é uma boa prática, quando ele usa o compilador para reforçar a intenção do software.

Uma pesquisa rápida por funções-membro privadas em javascript mostra que existe um princípio semelhante, embora qualquer pessoa possa ver seu código se puder usá-lo: http://www.crockford.com/javascript/private.html

Ruan Caiman
fonte