gpt4 book ai didi

c# - 如何在 javascript 中实现 C# 访问修饰符?

转载 作者:IT王子 更新时间:2023-10-29 03:07:15 28 4
gpt4 key购买 nike

  • 总结

    我尝试在 javascript 中正确地实现继承和封装,就像在基于类的语言(如 C#)中一样。

    丑陋的部分是 protected 成员在私有(private)实例中有多个副本,这些副本只能通过闭包访问,除了将这些成员刷新到私有(private)实例之外我没有别的想法。

    如果可能的话,我想在我的 Function.extend 代码中去掉 transmittransfer

  • 更新对于有兴趣引用或研究的人,这里是源代码存储库:

    https://github.com/kenkins/Function.extend

  • 故事

    因为 assemblies 可能是一个超出 javascript 范围的概念,所以我不考虑 internal 修饰符,而是考虑 publicprotectedprivate

    publicprivate 修饰符并不难实现;但是对于继承,protected 非常棘手。然而,不推荐使用 javascript,我读过的大多数文章都说使用特殊字符作为前缀并记录下来

    但似乎我坚持要制作 javascript 来模拟基于类的语言..我偷了 this idea并以我的方式实现,代码在这篇文章的后面。

    幕后的想法是将更高的可访问性与更高的原型(prototype)放在一起,并通过闭包访问最高的原型(prototype)。

    假设我们有三个原型(prototype)ADG,它看起来像

    BANxt.png

    因为一个对象不可能是一个类型的实例也是另一个不在原型(prototype)链中的类型的实例;我选择的方法是水平链接 protected 级别并从声明类型的原型(prototype)复制成员。这使得嵌套类成为可能,因为在派生较少的类型上声明的成员可以传播到派生较多的类型;我代码中的 transmit 方法就是这样做的。如果 ADG 有自己的 protected 成员,它看起来像:

    bhcsI.png

    访问私有(private)实例的闭包是this['']。它需要一个用于标识类的参数。 modifiers holder只是类标识符,在Function.extend中命名为y,在测试代码中命名为_,不应该暴露在外部类声明。它还用作 this[''] 的快捷方式。

    _['base'] 实际上不仅是基础构造函数的调用者,也是私有(private)实例的创建者。它创建私有(private)实例并为每个继承的构造函数更新 this[''],因此它应该始终在构造函数中调用。

    尽管私有(private)实例可以访问公共(public)成员,但不应该使用它来更改它们,因为不能保证在访问公共(public)成员时调用 this['']。但是私有(private)实例的访问是; recent 记住最近访问的私有(private)实例,并在有变化时更新 protected 成员。

    我的问题是,我怎样才能摆脱这种刷新 protected 成员的方式呢?是否有更好的想法来实现更现实的封装?

    p.s.:我实际上不想要一个使用非标准方法/属性的解决方案.. 如果使用的方法/属性对旧浏览器来说太时尚了,那么最好有 polyfills。


  • 函数.扩展

    Function.extend=function(base, factory) {
    factory.call(initializeClass);
    updateStaticMembersOfDerivedInnerClasses(y['public'].constructor);
    transfer(y['protected'], y['public']);
    return y['public'].constructor;

    function y($this) {
    return $this[''](y);
    }

    function transfer(target, source, descriptor) {
    if(target!==source?
    'undefined'!==typeof target?
    'undefined'!==typeof source:
    false:false) {
    var keys='undefined'!==typeof descriptor? descriptor:source;

    for(var key in keys) {
    if(Object.prototype.hasOwnProperty.call(source, key)) {
    target[key]=source[key];
    }
    }
    }
    }

    function updateStaticMembersOfDerivedInnerClasses(outer) {
    var member, inner;

    for(var key in outer) {
    if(Object.prototype.hasOwnProperty.call(outer, key)?
    (member=outer[key]) instanceof outer?
    outer!==(inner=member.constructor):
    false:false) {
    transfer(inner, outer);
    }
    }
    }

    function initializeInstance() {
    var $this=Object.create(y['private']);
    var derivedGet=this[''];
    var recent=$this;

    this['']=function(x) {
    var value=y!==x? derivedGet.call(this, x):$this;

    if(value!==recent) {
    transfer(value, recent, x['protected']);
    recent=value;
    }

    transfer(value, this);
    return value;
    };

    base.apply(this, arguments);
    $this['']=this[''];
    }

    function initializeClass(derived) {
    y['public']=Object.create(base.prototype);
    y['public'].constructor=derived;

    if(Object.prototype.hasOwnProperty.call(base, 'transmit')) {
    base.transmit(y);
    }
    else {
    y['protected']=Object.create(y['public']);
    }

    y['private']=Object.create(y['protected']);
    y['base']=initializeInstance;
    transfer(derived, base);

    derived.transmit=function(x) {
    if(x['public'] instanceof derived) {
    x['protected']=Object.create(y['protected']);
    x['protected'].constructor=x['public'].constructor;
    }
    };

    derived.prototype=y['public'];
    return y;
    }
    };
  • 测试代码

    'use strict';

    var BaseClass=Function.extend(Object, function () {
    var _=this(BaseClass);

    var NestedClass=Function.extend(BaseClass, function () {
    var _=this(NestedClass);

    function NestedClass(x, y, z) {
    _['base'].apply(this, arguments);
    _(this).Y=y;
    _(this).Z=z;
    }

    _['public'].SetX=function (x) {
    _(this).InternalSetX(x);
    };

    _['public'].GetX=function () {
    return _(this).InternalGetX();
    };

    _['public'].GetY=function () {
    return _(this).Y;
    };

    _['public'].SetZ=function (z) {
    _(this).Z=z;
    };

    _['public'].GetZ=function () {
    return _(this).Z;
    };

    _['private'].Y=0;
    });

    function BaseClass(x) {
    _['base'].apply(this, arguments);
    _(this).X=x;
    }

    _['protected'].InternalSetX=function (x) {
    _(this).X=x;
    };

    _['protected'].InternalGetX=function () {
    return _(this).X;
    };

    _['private'].X=0;
    _['protected'].Z=0;

    BaseClass.Sample=new NestedClass(1, 2, 3);
    });

    var DerivedClass=Function.extend(BaseClass, function () {
    var _=this(DerivedClass);

    function DerivedClass(x, y, z) {
    _['base'].apply(this, arguments);
    }
    });

    var o=DerivedClass.Sample;
    alert(o.GetX());
    alert(o.GetY());
    alert(o.GetZ());
    o.SetX(3);
    o.SetZ(1);
    alert(o.GetX());
    alert(o.GetY());
    alert(o.GetZ());

最佳答案

我也有类似的想法,决定尝试写点东西。 Vanilla js 解决方案。还早,但我喜欢结果。您可能也会发现它很有趣。

它不完全是 c#,但提供了更严格的生态系统。以及轻量级解决方案中的一些其他高级 js 功能。

https://github.com/iamlothian/rucksack.js

这不是针对您的代码的解决方案,而是针对您的概念的解决方案。如果您的目标是让您的想法付诸实现,那么一定要继续,因为我对结果很感兴趣。

如果你像我一样只是想要一个更结构化的 js 环境,那么这里是我写的一个与你的问题概念类似的野心。

第 2 部分:

这里的想法是使用闭包和访问限制来创建一种模式,限制代码在定义后可以使用和更改的方式。在大多数情况下,已经完成了许多艰苦的工作。但是模式留给您来定义。

这是一个快速模拟示例,演示了如何实现 public|protect|private 继承。我正在尝试决定是将其中的一些实现为内置功能,还是留给用户来实现他们自己的对象扩展,就像我在示例中所做的那样。

http://plnkr.co/edit/ao2hTyBV1b3nYIwr7ZS5

实现在 scripts.js 中。查看您的控制台以了解发生了什么。

rucksack 提供的是一个用于创建独立代码模块的框架。这些模块被分组到命名空间中,并且可以相互依赖。这些依赖项按照定义延迟解析,因此定义顺序并不重要。解析过程提供了一些其他有用的功能,例如接口(interface)匹配和密封模块。

当前功能:

  • 模块化
  • 依赖注入(inject)
  • 工厂构造函数(实例对象)
  • 服务构造函数(静态对象)
  • 延迟加载
  • 简单的错误记录(模块内的所有错误都被捕获并可以传递)
  • 命名空间
  • Sealable modules and namespaces(不能从命名空间外访问的模块)
  • 模块的全局等待事件
  • 可选配置对象的接口(interface)
  • 可选的注入(inject)严格接口(interface)检查

关于c# - 如何在 javascript 中实现 C# 访问修饰符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21126505/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com