Como suportar herança ao projetar uma linguagem OO sem classes

5

Estou projetando uma linguagem de programação para um jogo, para ser usada como a principal maneira de interagir com o jogo, ao invés de usar outros métodos de controle, como as teclas de seta ou o mouse. Meu plano é fazer com que o usuário controle os objetos do jogo por meio de objetos no idioma.

if unit1.health > 20 {

    unit1.attack(Enemies.enemy1)

}

Onde unit1 e enemy1 são os objetos. Isso pode ser feito com relativa facilidade, no entanto, eu também gostaria que a linguagem com a qual o usuário interage fosse uma linguagem real e que os objetos do jogo como unit1 se comportassem de maneira semelhante aos objetos criados pelo usuário.

Eu não pretendo adicionar classes ou algo similar. Todos os atributos de um objeto são públicos por padrão e somente leitura, e os métodos são apenas atributos que são objetos de função. Você também não pode adicionar atributos a um objeto. A única vez que o usuário pode acessar as entranhas de um objeto é na criação, pois isso é necessário para impedir que o usuário altere os objetos do jogo.

Existe alguma maneira de adicionar um recurso à linguagem que permita ao usuário fazer algo como herança ou algo que permita escrever facilmente códigos complexos, mantendo a linguagem "pura" e simples?

Neste momento, o máximo que você pode fazer é algo como:

fake_class = function(x, y) {
    {
        self.x = x
        self.y = y
        z = "hi" // private
        self.change_x_and_print_z = function(new) {
                                        self.x = new
                                        print(z)
                                    }
    }
}

new_obj = fake_class(4, 5)

Mas posso pensar em qualquer maneira de estender o objeto, já que ele é somente leitura e é mutável apenas dentro dele.

    
por Vityou 16.12.2017 / 02:56
fonte

2 respostas

5

Possibilita criar um novo objeto como um clone de um objeto existente com novas propriedades.

Então, por exemplo:

function Base() {
    z = 5
    return {
       x: 2,
       y: 4,
       print_z: function() {
           print(z)
       }
    }
}

function Child() {
     return {
         ...Base(), // start with copy of base
         g: 5,
         h: 3, // add my own stuff
     }
}
    
por 16.12.2017 / 03:50
fonte
3

Existem várias alternativas à herança baseada em classes que já foram exploradas

  • Delegação de protótipo: os objetos podem ter uma ou mais referências especiais para outros objetos. Quando um objeto não entende uma mensagem, a mensagem é encaminhada para os objetos referenciados por essas referências especiais . Algumas das primeiras linguagens que exploraram essa ideia foram Self e Act-1, a primeira comercial foi NewtonScript, e a mais famosa é a ECMAScript. As decisões de design são: single (ECMAScript) ou múltipla (Self), e se essas referências são ou não "mágicas" (ECMAScript) ou apenas campos regulares aos quais você pode atribuir à vontade (Self).

  • Mixin Inheritance: Mixins podem ser considerados como "classes parametrizadas sobre sua superclasse" ou como "pacotes compostáveis de métodos".

  • Composição do traço: Os traços são como mixins com dependências declaradas e resolução de conflitos (por exemplo, ocultação de métodos e renomeação).

O mais simples deles, conceitualmente, é a Delegação de Protótipo. É também aquele com o qual os usuários provavelmente estarão familiarizados, se tiverem se interessado em programação na web.

Em Auto, os protótipos são apenas campos regulares cujo nome termina com um asterisco * . As mensagens são reenviadas para os campos em ordem alfabética, até que alguém responda ou uma mensagem doesNotUnderstand: seja gerada, seguida das mesmas regras de pesquisa. Se a mensagem doesNotUnderstand: também não for respondida, será gerada uma exceção NoMethodFoundError .

Como os protótipos são apenas campos regulares, você pode criar, excluir e reatribuí-los à vontade, assim como todos os outros campos.

    
por 16.12.2017 / 12:51
fonte