你能 return Java/C# 中的超级吗? (如果可以的话会有用吗?)

Can you return the super in Java/C#? (would it be useful if u could?)

在我继续之前:
这是一个绝对抽象的问题。不要问你想做什么。

事情是这样的:
以两种不同的语法查看这两段代码。 (语法?)
我几乎只使用第二个,并且第二个附带了另一个无法实现的能力。
我不知道 Java/C#.
中的 OO 我想知道 Java/C# 在这个能力上的立场。
我的问题是关于这种能力,并且:
如果这种能力在 C#/Java 中是可能的? (我知道在第一种语法中是不可能的)
它在 C#/Java 中的 OO 原则方面完全有缺陷吗? (因为我想也许第一种语法不可能是有原因的)
这是一个不需要的东西吗?

虽然我不确定术语,但我所说的这种能力是恢复超级能力。

第一个语法:(这是 es6 的东西)

var log = console.log;

class Gender {
    constructor(type) {
        this.gender = type;
    }
    sayGender() {
        log(this.gender);
        return this;
    }
}
class Person extends Gender {
    constructor(gender, name, age) {
        super(gender);
        this.name = name;
        this.age = age;
    }
    sayName() {
        log(this.name);
        return this;
    }
    sayAge() {
        log(this.age);
        return this;
    }
    saySomething() {
    // only limited access to super methods.
    // access limited to calling super methods/getters/setters and not public properties.
    // (also not possible to return them since they're just imaginary refrences and not values)
    // this === invoked instance
    // super === reference to implicit derived instance (not returnable since not value)
    // no access to super/base instance (instance of Person)
    log("you can't break the chain here, even if u wanted to");
    return this;
}
class Employee extends Person {
    constructor(gender, name, age, jobTitle) {
        super(gender, name, age);
        this.jobTitle = jobTitle;
    }
    sayJob() {
        log(this.jobTitle);
        return this;
    }
}

这是第二种语法

var log = console.log;
function newGender(type) {
    let inst = {};
    inst.gender = type;

    inst.sayGender = function () {
        log(gender); // or this.gender if u want (but context-less calls will no longer be available)
        return this;
    };

    return inst;
}
function newPerson(gender, name, age) {
    let _super_ = newGender(gender);
    let inst = Object.create( _super_ );

    let privateVariable;
    function privateFunction() {} // not possible with the other syntax

    inst.name = name;
    inst.age = age;

    inst.sayName = function () {
        log(name);
        return this;
    };
    inst.sayAge = function () {
        log(age);
        return this;
    };
    inst.saySomething = function () {
    // full access to super/base, derived, and invoked instances. (even returning them since they're values now).
    // differentiation between super/base, derived, and invoked instances in the context of current class.
    // _super_ === base instance
    // inst === derived instance
    // this === invoked instance
    log("you can break the chain here if u want");
    return inst;
    };

    return inst;
}
function newEmployee(gender, name, age, jobTitle) {
    let _super_ = newPerson(gender, name, age);
    let inst = Object.create( _super_ );

    inst.jobTitle = jobTitle;

    inst.sayJob = function () {
        log(jobTitle);
        return this;
    };

    return inst;
}

差异:

方法链接:

var t = new Employee("male", "mohammad", 28, "web developer")
t.sayGender()        //  "male"
    .sayName()       //  "mohammad"
    .sayAge()        //  28
    .saySomething()  //  "you can't break the chain here, even if u wanted to"
    .sayJob()        //  "web developer"

var t = newEmployee("male", "mohammad", 28, "web developer")
t.sayGender()        //  "male"
    .sayName()       //  "mohammad"
    .sayAge()        //  28
    .saySomething()  //  "you can break the chain here if u want"
    // I can't chain after this point since I returned the super and sayJob() is not defined on it.
    .sayJob()        //  "web developer"

无上下文调用:

var t = new Employee("male", "mohammad", 28, "web developer")
var sayJob = t.sayJob;
sayJob() // TypeError: Cannot read property 'jobTitle' of undefined

var t = newEmployee("male", "mohammad", 28, "web developer")
var sayJob = t.sayJob;
sayJob() // web developer

编辑:

问题与 Java 或 C# 或 JavaScript 无关。

当您在 Java 脚本中调用派生 class 的构造函数时(使用 new
有一个隐式超级实例可用于您的派生实例(因为所有派生 class 构造函数必须包含一个 super() 调用)。但是您只能使用此隐式实例的方法(和 getters/setters),而不能使用属性。
所以在 Person class 的 sayName() 方法中,我可以说 super.someMethod()super["name of a setter"] = "a value";super["name of a getter"]; // and u can read it

所以我可以访问超级实例,但我的访问权限有限。 因此,为什么你不能 return 它,是的,我知道 super 不是一个值 =)))).
现在假设您可以完全访问 super 指向的实例。对吗?
我所说的完全访问的意思是想象你在那里得到那个实例作为一个值,所以现在你可以 return 它或其他任何东西。

我要问你的是,如果你是一名 Java/C# 开发人员并且你经常使用层次继承并且有这方面的经验,明天我会出现在你工作的地方,或者给你发电子邮件或其他东西,我会告诉你我有一个大消息要告诉你:
从今天起,Java/C# lang:
将有两个变化 1 super 现在指向基础 class 实例。
2 super 现在是一个值,是派生的 class 上下文中的实际实例,您可以用它做任何想做的事。你甚至可以 RETURN 它在一个方法中!!!
你怎么说?你都有些什么想法呢?

(一个场景是现在一个方法可以 return 超级实例,如果有人从外部链接一些方法并调用这个方法,下一个将被 returned 的实例将不再有派生实例方法)

最终编辑:在评论讨论后我会写这个问题的方式(虽然我不确定这种方式是否更好,因为它更长):

在 JavaScript a class 中,行为如下:(当我说 class 我的意思是我们假装它的假 classical 继承与底层原型系统一起)
它必须有一个构造函数,当您使用 new kewrod (var t = new Person()) 实例化它并获得该 class 的实例(或对象)时调用该构造函数。 因此,当您定义 class 时,例如:

class Person() { // from this curly

} // to this curly  

您可以引用将在有人调用 new 时创建的实例。
到目前为止还不是一件复杂的事情。我们继续吧。 所以一个 class 可以从另一个 class 派生出来。这件事增加了复杂性。为什么?好吧,让我们看看:
现在我们必须检查派生的 class.
的行为 派生 class 与基础 class 具有相同的行为,除了以下几个:
派生的 class 有一个构造函数,在这些卷曲中你可以引用实例(它将在调用 new 之后创建),所有这些,就像基础 class 一样。
但是派生 class 有一些行为与基础 class 不相同。所以让我们通过它们,这是一个派生的 class 定义:

class Employee extends Person {
    constructor() {
        super()
    }
}

一个派生的class虽然有一个构造函数就像一个基础class,它还有一个额外的规则是:它的构造函数必须包含一个super()调用,那是什么它会调用基础 class 构造函数吗?所以现在在派生的 class 的花边内,除了 this 关键字(这是要创建的实例)之外,我们还有一个 super 关键字。
super 关键字允许你做的是像 this 一样引用一个对象,除了它不是你调用 new 时你会得到的对象,不,它不是那个对象,它是如果你实例化基础 class (new Person()),你将获得的对象,但它与你手动实例化基础 class 不同,它有何不同?它的不同之处在于,如果您使用 new 调用手动实例化该基础 class,您将获得所有 public 方法、属性、getter 和设置器class。但这并不完全是 super 关键字所发生的事情。
因此,使用 super 关键字,尽管您实际上是在引用基 class 的实例,并且该基 class 的(隐式)实例可用于您的派生实例(在卷曲内) ,您无法访问该实例的属性(甚至是 public 属性),您只能使用 public 方法。 (虽然在 es6 js 中没有 public private,但我们假设它是。就像打字稿一样)。
所以现在我们看到在 devided class 的卷曲内我们可以访问该实例,虽然仅限于方法,但仍然可以访问并且重要的是要记住 super 关键字就像一个虚构的东西并且是不是一个值。

到目前为止一切正常,没有什么特别的。这是我的困境:
由于 JavaScript 内部系统,我有一个能力可以让我在构建对象时有一个选择,让我们看看那个能力是什么,更重要的是最后我关于那个能力的问题:
我一直提到的这个能力是:
记住我说过:super 就像是您手动实例化但有限制的基础 class 的实例吗?现在我可以将 super 视为我手动实例化的基 class 的一个实例。所以现在我不仅可以不受 super 的限制访问它的所有成员(属性和方法),而且因为它现在是一个值,所以我也可以在派生方法中访问 return 它,并导致链条断裂(我觉得这有点像不拥有和不需要等等交易更好)。

以下是我目前能想到的两个能力:

#1 一方面是当你使用 class 语法链接方法时,我总是有一个实例,一个对象。并在链中迈出一步之后。我可以访问该实例的所有方法,而其中一些方法是拥有的,而其中一些是继承的这一事实并不重要。但是有了 super 这种价值,我可以在那个链条中设置停止符。那么它有什么用呢?好吧,我不确定,但我现在能想到的是,也许我可以通过提示来区分拥有的方法和继承的方法。所以现在如果一个方法打破了链条,我知道该方法是在层次结构的某个地方继承的。

#2 另一方面是无上下文调用,但让我们忽略它,因为我不确定 Java/C# 中是否有这样的东西。 (但要明确一点:无上下文调用意味着您在没有上下文的情况下调用该方法,或者换句话说,没有提供 this 关键字应指向哪个对象)。

这两个能力让我感到困惑,因为我不知道 O-O 中的推理方式(就像我的手背一样),所以虽然我喜欢这些能力,但我不确定他们会把系统引向何方。而且我不知道如何衡量它或如何预见它的未来,所以我想征求Java/C#程序员的意见。

P.S。两个更新的答案都是被接受的答案。

这个答案是针对 Java 的,尽管我相信它对于 C# 也是一样的。

thissuper 都是同一个对象。作为对象引用,没有区别。

所以,没有必要return super,所以这不是有效的语法,但是你可以return this,也是对super.

的引用

更新

更新后的问题是关于方法链,是否可以从一个方法 return 基础 class ,所以链中的下一个方法调用不能使用 subclass.

答案是肯定的,也不是。

是的,您可以将声明的方法 return 类型更改为基础 class。由于 Java 是静态类型的,因此只有在基础 class 中声明的方法才可用于下一个方法调用。

不,您不能完全限制对基础 class 方法的方法调用,因为 returned 对象仍然是子 class,即使编译器不这样做知道这一点,任何被 subclass 覆盖 的基 class 方法仍然会调用 subclass 方法,即使声明的类型是基础 class.

这种差异是 class 与原型继承模型的一个方面,也是两种语言的静态类型与动态类型(Java 与 Java脚本,分别)。

Java 不允许您使用 super 作为值。你不能 return 它。而且您不需要 return 它,因为您可以使用 this.

引用该对象

在Java中,class的实例由一个对象表示。 superclass 不由单独的对象表示。

类 支持从 superclass 继承实现。这允许我们编写由 subclasses 使用或覆盖的通用代码。

超级classes和接口支持polymorphism. For example, a reference of a superclass type can be used to call methods from a subclass object. This allows us to exploit the Liskov Substitution Principle to write code once that can handle multiple types. This helps us not repeat ourselves. From the Java Language Specification, section 1.1: 1.1 Organization of the Specification:

Classes support single implementation inheritance, in which the implementation of each class is derived from that of a single superclass ... Variables of a class type can reference an instance of that class or of any subclass of that class, allowing new types to be used with existing methods, polymorphically.

Java 确实允许您使用关键字 super 来引用超级 class -- 但仅限于:

  • 调用带参数的超级class构造函数
  • 从 subclass.
  • 中访问 superclass 的成员

详情

来自 Java 语言规范,第 8.8.7.1 节,Explicit constructor invocations

Superclass constructor invocations begin with either the keyword super (possibly prefaced with explicit type arguments) or a Primary expression or an ExpressionName. They are used to invoke a constructor of the direct superclass.

来自 Java 语言规范,第 15.11.2 节,Accessing Superclass Members using super

The form super.Identifier refers to the field named Identifier of the current object, but with the current object viewed as an instance of the superclass of the current class.

所以super是关键字。但是该语言不支持使用 super 作为值。