可以对继承建模吗?

时间:2019-11-06 13:58:58

标签: javascript inheritance

这个问题的主要信息来源是James Shore在以下地址提供的教程:http://www.objectplayground.com/ ... ...多次重看视频后,我带走了足够的精力来整理一系列课程,但我仍然无法真正了解幕后情况。 James解释经典模型继承的方式(我认为是指使用类来组织数据,而不是使用较旧的处理方式)是这样的:

评估任何函数定义语句时,都会创建两个对象。创建的第一个对象是构造函数(出于这个问题的目的,我将其称为cStruct),并且可以通过其称为原型的成员进行识别,据他所说,原型和许多其他来源都指向 Function对象原型Function.prototype。但是然后变得很奇怪,因为创建的第二个对象是原型(或proType),而原型又可以由其自己的称为构造函数的成员(指向cStruct)进行标识,并拥有自己的原型成员指向 Object Object Prototype ,或者仅指向Object.prototype。好的,足够简单(哈!),但随后他(和其他消息来源)继续;当一个类扩展到另一个类时,我们放弃扩展的(较新/较窄的)类proType,而将其替换为实际上指向扩展的(原始/较旧/较宽的)类proType的一个新类。

好的,因此,根据此描述,我试图仅使用具有null原型作为构建基块的对象来重新创建继承模型,以便我可以在控制台中检查结果而不必仔细检查所有内容。还不明白基本上,我正在寻找继承的烟枪;证明这不仅是魔术,。看起来应该有可能,但是一旦逻辑以代码形式建立,就不会令人惊讶地无法传递继承的属性。您会明白我的意思。

常规练习-三个课程

function ExampleClass_A (  ) {  }
function ExampleClass_B (  ) {  }
function ExampleClass_C (  ) {  }

文学解释

注意 这些是字面模拟的类。他们证明了我理解编写班级时幕后发生的事情。请注意,在我们稍后开始扩展类之前,c变量几乎可以被忽略

a = Object.create( null );
b = Object.create( null );
c = Object.create( null );  // this represents the Object Prototype
cStruct_A               = a;
proType_A               = b;
proType_A.prototype     = c;
cStruct_A.prototype     = b;
proType_A.constructor   = a;
delete a; delete b;

a = Object.create( null );
b = Object.create( null );
cStruct_B               = a;
proType_B               = b;
proType_B.prototype     = c;
cStruct_B.prototype     = b;
proType_B.constructor   = a;
delete a; delete b;

a = Object.create( null );
b = Object.create( null );
cStruct_C               = a;
proType_C               = b;
proType_C.prototype     = c;
cStruct_C.prototype     = b;
proType_C.constructor   = a;
delete a; delete b; delete c;

常用练习-线性类扩展

编辑 @Vog,我不确定对象的组成是什么,但是如果我不得不猜测这是线性扩展的另一种类扩展/实例化模式我在这个问题中写过一篇文章,其中我必须假设某种形式的继承无论如何都在发生。当然,我当然不准备将一种模式接受到另一种模式,因为我只是想了解一开始使这些模式可行的机制是如何起作用的。

ExampleClass_B.prototype = Object.create( ExampleClass_A.prototype );
ExampleClass_C.prototype = Object.create( ExampleClass_B.prototype );

文学解释

注意 如果我正确理解这一点,则继承要工作于主类之后的所有子类的proType或彼此必须指向proType其父类。因此,这里我们取消了三个类proType中的两个,而将它们替换为指向适当的“后续”位置的类。

a                       = Object.create( null );
a.prototype             = proType_A;
a.constructor           = cStruct_B;
alt_proType_B           = a;
cStruct_B.prototype     = alt_proType_B;
delete proType_B;
delete a;

a                       = Object.create( null );
a.prototype             = alt_proType_B;
a.constructor           = cStruct_C;
alt_proType_C           = a;
cStruct_C.prototype     = alt_proType_C;
delete proType_C;
delete a;

常用练习-实例化

var exampleInstance_W = new ExampleClass_A();   //  
var exampleInstance_R = new ExampleClass_B();   //  randomly chosen names
var exampleInstance_T = new ExampleClass_C();   //  

文学解释

a = Object.create( null );
a.prototype             = proType_A;
nstance_W               = a;
delete a;

a = Object.create( null );
a.prototype             = alt_proType_B;
nstance_R               = a;
delete a;

a = Object.create( null );
a.prototype             = alt_proType_C;
nstance_T               = a;
delete a;

常用练习-作业

ExampleClass_A.prototype.prop_a = "test a,";
ExampleClass_B.prototype.prop_b = "test b,";
ExampleClass_C.prototype.prop_c = "test c";

文学解释

注意 在这里我开始看到可能有问题

cStruct_A.prototype.prop_a = "test a,";
cStruct_B.prototype.prop_b = "test b,";
cStruct_C.prototype.prop_c = "test c";

//  proType_A.prop_a = "test a";    //
//  proType_B.prop_b = "test b";    //  Kind of cool that this works
//  proType_C.prop_c = "test c";    //

测试 ---常规做法

console.log(
    exampleInstance_T.prop_a,  //  successful log
    exampleInstance_T.prop_b,  //  successful log
    exampleInstance_T.prop_c,  //  successful log
);

测试-文字解释

注意 现在将所有努力推向高潮。这些日志产生不同的结果令人困惑...

console.log(
    nstance_T.prototype.prop_a,     //  unsuccessful log
    nstance_T.prototype.prop_b,     //  unsuccessful log
    nstance_T.prototype.prop_c,     //  successful log
);

console.log(
    nstance_R.prototype.prop_a,     //  unsuccessful log
    nstance_R.prototype.prop_b,     //  successful log
    nstance_R.prototype.prop_c,     //  unsuccessful log
);

console.log(
    nstance_W.prototype.prop_a,     //  successful log
    nstance_W.prototype.prop_b,     //  unsuccessful log
    nstance_W.prototype.prop_c,     //  unsuccessful log
);

console.log(                        //  Kind of lame that this does't work
    nstance_W.prop_a,               //  
    nstance_R.prop_b,               //  I mean it makes sense when you follow the
    nstance_T.prop_c,               //  established logic, but at the same time
);                                  //  it means that I'm missing something.

换句话说,如果每个 文学解释 代码块都只是在模仿上面的 Common Practice 代码块它为何nstance_t不能访问.prop_a.prop_b?与我的配置有关吗?我错过了重点吗?帮帮我。预先感谢。

2 个答案:

答案 0 :(得分:1)

  

nstance_t为什么不能访问.prop_a.prop_b?与我的配置有关吗?我错过了重点吗?

似乎您期望.prototype建立一个对象的继承链。它不是,它只是一个普通属性,分配它不会带来任何神奇的作用。

对对象(或null)的实际引用是内部的,通常表示为 [[prototype]] 。您需要调用Object.getPrototypeOf(…)才能访问它。要进行设置,可以使用Object.createObject.setPrototypeOfnew

我相信这是您正在寻找的代码:

常用练习-ES6

class A {}
class B extends B {}
const instance = new B

常规练习-ES5

function A() {}
function B() {}
B.prototype = Object.create(A.prototype)
B.prototype.constructor = B
const instance = new B

文字解释(关于对象关系,忽略构造函数调用)

A_prototype = Object.create(Object.prototype)
A_constructor = new Function(…)
A_prototype.constructor = A_constructor
A_constructor.prototype = A_prototype

B_prototype = Object.create(A_constructor.prototype)
B_constructor = new Function(…)
B_prototype.constructor = B_constructor
B_constructor.prototype = B_prototype

instance = Object.create(B_constructor.prototype)

您现在可以在A_prototype / A_constructor.prototypeB_prototype / B_constructor.prototype上分配属性,并在instance上继承它们。

答案 1 :(得分:0)

尽管我赞扬您对构建这种东西的好奇心,但请注意继承是一种众所周知的反模式。 (经典)面向对象程序设计的其他方面在“今天”受到质疑(从某种意义上说:最近十年,如果不是更长的话)。但是,继承是几乎所有有经验的程序员都会建议的东西。

这里的口头禅是在可能的情况下始终使用对象组合而不是继承(我认为实际上总是这样)。

这与在JavaScript之上对适当的类型系统进行建模不同。或者,建模解构和结构模式匹配。这些玩具也可能永远不会在生产中使用,但是至少您会构建一些东西,以后再实际使用“真实”。

请注意,继承在任何语言中都没有实现其承诺,例如C ++,Python,Ruby,PHP,Smalltalk,Java等。即使在GoF书(https://en.wikipedia.org/wiki/Design_Patterns)中,您也可以找到早期的提示,这对大多数OO程序员来说都是一本圣经。在那里,尽管没有直接批评继承,但您可以将模式的整个小节总结为“如何用易于维护的对象组成结构替换难以维护的继承结构”。