JS backend: fix override property
This commit is contained in:
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2013 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.k2js.test.semantics;
|
||||||
|
|
||||||
|
import org.jetbrains.k2js.test.SingleFileTranslationTest;
|
||||||
|
|
||||||
|
public class PropertyOverrideTest extends SingleFileTranslationTest {
|
||||||
|
|
||||||
|
public PropertyOverrideTest() {
|
||||||
|
super("propertyOverride/");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOverrideValWithBackendFiled() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSimpleOverride() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOverloadPrivateVal() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOverrideValFromTraits() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCheckSupertypeOrder() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOverrideNotDirectlySuper() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOverrideExtensionProperty() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -167,6 +167,10 @@ public final class Namer {
|
|||||||
private final JsName enumEntriesName;
|
private final JsName enumEntriesName;
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JsExpression undefinedExpression;
|
private final JsExpression undefinedExpression;
|
||||||
|
@NotNull
|
||||||
|
private final JsExpression callGetProperty;
|
||||||
|
@NotNull
|
||||||
|
private final JsExpression callSetProperty;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JsName isTypeName;
|
private final JsName isTypeName;
|
||||||
@@ -179,6 +183,9 @@ public final class Namer {
|
|||||||
definePackage = kotlin("definePackage");
|
definePackage = kotlin("definePackage");
|
||||||
defineRootPackage = kotlin("defineRootPackage");
|
defineRootPackage = kotlin("defineRootPackage");
|
||||||
|
|
||||||
|
callGetProperty = kotlin("callGetter");
|
||||||
|
callSetProperty = kotlin("callSetter");
|
||||||
|
|
||||||
className = kotlinScope.declareName(CLASS_OBJECT_NAME);
|
className = kotlinScope.declareName(CLASS_OBJECT_NAME);
|
||||||
enumEntriesName = kotlinScope.declareName(ENUM_ENTRIES_NAME);
|
enumEntriesName = kotlinScope.declareName(ENUM_ENTRIES_NAME);
|
||||||
objectName = kotlinScope.declareName(OBJECT_OBJECT_NAME);
|
objectName = kotlinScope.declareName(OBJECT_OBJECT_NAME);
|
||||||
@@ -288,4 +295,14 @@ public final class Namer {
|
|||||||
public JsExpression getUndefinedExpression() {
|
public JsExpression getUndefinedExpression() {
|
||||||
return undefinedExpression;
|
return undefinedExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JsExpression getCallGetProperty() {
|
||||||
|
return callGetProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JsExpression getCallSetProperty() {
|
||||||
|
return callSetProperty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import static org.jetbrains.k2js.translate.utils.AnnotationsUtils.*;
|
import static org.jetbrains.k2js.translate.utils.AnnotationsUtils.*;
|
||||||
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.*;
|
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.*;
|
||||||
|
import static org.jetbrains.k2js.translate.utils.TranslationUtils.getMangledName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aggregates all the static parts of the context.
|
* Aggregates all the static parts of the context.
|
||||||
@@ -300,6 +301,9 @@ public final class StaticContext {
|
|||||||
String propertyName = propertyDescriptor.getName().asString();
|
String propertyName = propertyDescriptor.getName().asString();
|
||||||
|
|
||||||
if (!isExtension(propertyDescriptor)) {
|
if (!isExtension(propertyDescriptor)) {
|
||||||
|
if (propertyDescriptor.getVisibility() == Visibilities.PRIVATE) {
|
||||||
|
propertyName = getMangledName(propertyDescriptor, propertyName);
|
||||||
|
}
|
||||||
return declarePropertyOrPropertyAccessorName(descriptor, propertyName, false);
|
return declarePropertyOrPropertyAccessorName(descriptor, propertyName, false);
|
||||||
} else {
|
} else {
|
||||||
if (descriptor instanceof PropertyDescriptor) {
|
if (descriptor instanceof PropertyDescriptor) {
|
||||||
|
|||||||
+1
-1
@@ -58,7 +58,7 @@ public final class PropertyTranslator extends AbstractTranslator {
|
|||||||
@Nullable JetProperty declaration,
|
@Nullable JetProperty declaration,
|
||||||
@NotNull List<JsPropertyInitializer> result,
|
@NotNull List<JsPropertyInitializer> result,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
if (!JsDescriptorUtils.isSimpleProperty(descriptor)) {
|
if (!JsDescriptorUtils.isSimpleFinalProperty(descriptor)) {
|
||||||
new PropertyTranslator(descriptor, declaration, context).translate(result);
|
new PropertyTranslator(descriptor, declaration, context).translate(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,8 +186,12 @@ public final class CallTranslator extends AbstractTranslator {
|
|||||||
return callType.constructCall(receiver, new CallType.CallConstructor() {
|
return callType.constructCall(receiver, new CallType.CallConstructor() {
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public JsExpression construct(@Nullable JsExpression receiver) { // TODO: support super val access
|
public JsExpression construct(@Nullable JsExpression receiver) {
|
||||||
assert receiver != null;
|
assert receiver != null : "Receiver for superCall must be not null";
|
||||||
|
if (isDirectPropertyAccess()) {
|
||||||
|
return superPropertyAccess(receiver, getPropertyName());
|
||||||
|
}
|
||||||
|
|
||||||
JsExpression qualifiedCallee = getQualifiedCallee(Namer.getRefToPrototype(receiver));
|
JsExpression qualifiedCallee = getQualifiedCallee(Namer.getRefToPrototype(receiver));
|
||||||
qualifiedCallee = Namer.getFunctionCallRef(qualifiedCallee);
|
qualifiedCallee = Namer.getFunctionCallRef(qualifiedCallee);
|
||||||
List<JsExpression> arguments = new ArrayList<JsExpression>(CallTranslator.this.arguments.size() + 1);
|
List<JsExpression> arguments = new ArrayList<JsExpression>(CallTranslator.this.arguments.size() + 1);
|
||||||
@@ -198,6 +202,25 @@ public final class CallTranslator extends AbstractTranslator {
|
|||||||
}, context());
|
}, context());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private JsStringLiteral getPropertyName() {
|
||||||
|
assert descriptor instanceof PropertyAccessorDescriptor;
|
||||||
|
String propertyName = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty().getName().asString();
|
||||||
|
return context().program().getStringLiteral(propertyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private JsExpression superPropertyAccess(@NotNull JsExpression classRef, @NotNull JsStringLiteral propertyName) {
|
||||||
|
if (descriptor instanceof PropertyGetterDescriptor) {
|
||||||
|
assert arguments.isEmpty();
|
||||||
|
return new JsInvocation(context().namer().getCallGetProperty(), JsLiteral.THIS, classRef, propertyName);
|
||||||
|
} else {
|
||||||
|
assert descriptor instanceof PropertySetterDescriptor;
|
||||||
|
assert arguments.size() == 1;
|
||||||
|
return new JsInvocation(context().namer().getCallSetProperty(), JsLiteral.THIS, classRef, propertyName, arguments.get(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression methodCall(@Nullable JsExpression receiver) {
|
private JsExpression methodCall(@Nullable JsExpression receiver) {
|
||||||
return callType.constructCall(receiver, new CallType.CallConstructor() {
|
return callType.constructCall(receiver, new CallType.CallConstructor() {
|
||||||
|
|||||||
@@ -136,10 +136,11 @@ public final class JsDescriptorUtils {
|
|||||||
return accessorDescriptor == null || accessorDescriptor.isDefault();
|
return accessorDescriptor == null || accessorDescriptor.isDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSimpleProperty(@NotNull PropertyDescriptor propertyDescriptor) {
|
public static boolean isSimpleFinalProperty(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||||
return !isExtension(propertyDescriptor) &&
|
return !isExtension(propertyDescriptor) &&
|
||||||
isDefaultAccessor(propertyDescriptor.getGetter()) &&
|
isDefaultAccessor(propertyDescriptor.getGetter()) &&
|
||||||
isDefaultAccessor(propertyDescriptor.getSetter());
|
isDefaultAccessor(propertyDescriptor.getSetter()) &&
|
||||||
|
!propertyDescriptor.getModality().isOverridable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isStandardDeclaration(@NotNull DeclarationDescriptor descriptor) {
|
public static boolean isStandardDeclaration(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyGetterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyGetterDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.Visibilities;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.k2js.translate.context.TemporaryConstVariable;
|
import org.jetbrains.k2js.translate.context.TemporaryConstVariable;
|
||||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||||
@@ -33,6 +34,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.google.dart.compiler.backend.js.ast.JsBinaryOperator.*;
|
import static com.google.dart.compiler.backend.js.ast.JsBinaryOperator.*;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getFQName;
|
||||||
import static org.jetbrains.k2js.translate.context.Namer.getKotlinBackingFieldName;
|
import static org.jetbrains.k2js.translate.context.Namer.getKotlinBackingFieldName;
|
||||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
|
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
|
||||||
import static org.jetbrains.k2js.translate.utils.JsAstUtils.assignment;
|
import static org.jetbrains.k2js.translate.utils.JsAstUtils.assignment;
|
||||||
@@ -129,14 +131,24 @@ public final class TranslationUtils {
|
|||||||
return new JsConditional(testExpression, thenExpression, elseExpression);
|
return new JsConditional(testExpression, thenExpression, elseExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static String getMangledName(@NotNull PropertyDescriptor descriptor, @NotNull String suggestedName) {
|
||||||
|
int absHashCode = Math.abs(getFQName(descriptor).asString().hashCode());
|
||||||
|
return suggestedName + "_" + Integer.toString(absHashCode, Character.MAX_RADIX) + "$";
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsNameRef backingFieldReference(@NotNull TranslationContext context,
|
public static JsNameRef backingFieldReference(@NotNull TranslationContext context,
|
||||||
@NotNull PropertyDescriptor descriptor) {
|
@NotNull PropertyDescriptor descriptor) {
|
||||||
JsName backingFieldName = context.getNameForDescriptor(descriptor);
|
JsName backingFieldName = context.getNameForDescriptor(descriptor);
|
||||||
if(!JsDescriptorUtils.isSimpleProperty(descriptor)) {
|
if(!JsDescriptorUtils.isSimpleFinalProperty(descriptor)) {
|
||||||
backingFieldName = context.declarePropertyOrPropertyAccessorName(descriptor,
|
String backingFieldMangledName;
|
||||||
getKotlinBackingFieldName(backingFieldName.getIdent()),
|
if (descriptor.getVisibility() != Visibilities.PRIVATE) {
|
||||||
false);
|
backingFieldMangledName = getMangledName(descriptor, getKotlinBackingFieldName(backingFieldName.getIdent()));
|
||||||
|
} else {
|
||||||
|
backingFieldMangledName = getKotlinBackingFieldName(backingFieldName.getIdent());
|
||||||
|
}
|
||||||
|
backingFieldName = context.declarePropertyOrPropertyAccessorName(descriptor, backingFieldMangledName, false);
|
||||||
}
|
}
|
||||||
return new JsNameRef(backingFieldName, JsLiteral.THIS);
|
return new JsNameRef(backingFieldName, JsLiteral.THIS);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package foo
|
package foo
|
||||||
|
|
||||||
open class A(open val bar: Int = 2) {
|
open class A(open val bar: Int = 2) {
|
||||||
val barA = bar
|
val barA = $bar
|
||||||
}
|
}
|
||||||
|
|
||||||
class B(override val bar: Int = 3) : A()
|
class B(override val bar: Int = 3) : A()
|
||||||
|
|||||||
@@ -236,6 +236,14 @@ var Kotlin = {};
|
|||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Kotlin.callGetter = function(thisObject, klass, propertyName) {
|
||||||
|
return klass.$metadata$.properties[propertyName].get.call(thisObject);
|
||||||
|
};
|
||||||
|
|
||||||
|
Kotlin.callSetter = function(thisObject, klass, propertyName, value) {
|
||||||
|
klass.$metadata$.properties[propertyName].set.call(thisObject, value);
|
||||||
|
};
|
||||||
|
|
||||||
function isInheritanceFromTrait (objConstructor, trait) {
|
function isInheritanceFromTrait (objConstructor, trait) {
|
||||||
if (isNativeClass(objConstructor) || objConstructor.$metadata$.classIndex < trait.$metadata$.classIndex) {
|
if (isNativeClass(objConstructor) || objConstructor.$metadata$.classIndex < trait.$metadata$.classIndex) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
trait A {
|
||||||
|
val bal: Int
|
||||||
|
get() {
|
||||||
|
return 42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class B {
|
||||||
|
open val bal = 239
|
||||||
|
}
|
||||||
|
|
||||||
|
class C1: B(), A {
|
||||||
|
override val bal: Int = 14
|
||||||
|
|
||||||
|
fun getBalA(): Int {
|
||||||
|
return super<A>.bal
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBalB(): Int {
|
||||||
|
return super<B>.bal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class C2: A, B() {
|
||||||
|
override val bal: Int = 14
|
||||||
|
|
||||||
|
fun getBalA(): Int {
|
||||||
|
return super<A>.bal
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBalB(): Int {
|
||||||
|
return super<B>.bal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val c1 = C1();
|
||||||
|
if (c1.bal != 14) return "c1.bal != 14, it: ${c1.bal}"
|
||||||
|
if (c1.getBalA() != 42) return "c1.getBalA() != 42, it: ${c1.getBalA()}"
|
||||||
|
if (c1.getBalB() != 239) return "c1.getBalB() != 239, it: ${c1.getBalB()}"
|
||||||
|
|
||||||
|
val c2 = C2();
|
||||||
|
if (c2.bal != 14) return "c2.bal != 14, it: ${c2.bal}"
|
||||||
|
if (c2.getBalA() != 42) return "c2.getBalA() != 42, it: ${c2.getBalA()}"
|
||||||
|
if (c2.getBalB() != 239) return "c2.getBalB() != 239, it: ${c2.getBalB()}"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
open class A {
|
||||||
|
private val a = 1
|
||||||
|
|
||||||
|
private val b = 2
|
||||||
|
get() {
|
||||||
|
return $b + 10 + 100 * a
|
||||||
|
}
|
||||||
|
fun getBInA(): Int {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
val a = 13
|
||||||
|
val b = 42
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val b = B()
|
||||||
|
if (b.getBInA() != 112) return "b.getBInA() != 112, it: ${b.getBInA()}"
|
||||||
|
|
||||||
|
if (b.a != 13) return "b.a != 13, it: ${b.a}"
|
||||||
|
if (b.b != 42) return "b.b != 42, it: ${b.b}"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
class T
|
||||||
|
|
||||||
|
open class A {
|
||||||
|
open val T.foo: Int = 34
|
||||||
|
get() {
|
||||||
|
return $foo
|
||||||
|
}
|
||||||
|
fun test(): Int {
|
||||||
|
return T().foo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
override val T.foo: Int = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
if (A().test() != 34) return "A().test() != 34, it: ${A().test() != 34}"
|
||||||
|
if (B().test() != 5) return "B().test() != 5, it: ${B().test() != 5}"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
open class A {
|
||||||
|
open var a = 1
|
||||||
|
fun getAInA(): Int = a
|
||||||
|
}
|
||||||
|
|
||||||
|
open class AA: A()
|
||||||
|
|
||||||
|
class B : AA() {
|
||||||
|
override var a = 2
|
||||||
|
|
||||||
|
fun getSuperA(): Int {
|
||||||
|
return super.a
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setSuperA(value: Int) {
|
||||||
|
super.a = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a = A()
|
||||||
|
val b = B()
|
||||||
|
if (a.getAInA() != 1) return "a.getAInA() != 1, it: ${a.getAInA()}"
|
||||||
|
if (b.getAInA() != 2) return "b.getAInA() != 2, it: ${b.getAInA()}"
|
||||||
|
|
||||||
|
if (b.getSuperA() != 1) return "b.getSuperA() != 1, it: ${b.getSuperA()}"
|
||||||
|
b.setSuperA(3)
|
||||||
|
if (b.getSuperA() != 3) return "b.getSuperA() != 3, it: ${b.getSuperA()}"
|
||||||
|
|
||||||
|
if (b.getAInA() != 2) return "b.getAInA() != 2 after b.setAInB(3), it: ${b.getAInA()}"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
trait A {
|
||||||
|
val bal: Int
|
||||||
|
get() {
|
||||||
|
return 5
|
||||||
|
}
|
||||||
|
var bar: Int
|
||||||
|
get() {
|
||||||
|
return realBar
|
||||||
|
}
|
||||||
|
set(value: Int) {
|
||||||
|
realBar = value
|
||||||
|
}
|
||||||
|
|
||||||
|
var realBar: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
trait B {
|
||||||
|
val bal: Int
|
||||||
|
get() {
|
||||||
|
return 42
|
||||||
|
}
|
||||||
|
var bar: Int
|
||||||
|
get() {
|
||||||
|
return realBar + 1000
|
||||||
|
}
|
||||||
|
set(value: Int) {
|
||||||
|
realBar = value + 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
var realBar: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
class C: A, B {
|
||||||
|
override val bal: Int = 1
|
||||||
|
override var bar: Int = 2
|
||||||
|
get() {
|
||||||
|
return $bar + 20
|
||||||
|
}
|
||||||
|
set(value: Int) {
|
||||||
|
$bar = value + 20
|
||||||
|
}
|
||||||
|
override var realBar: Int = 3
|
||||||
|
|
||||||
|
fun supBalA(): Int {
|
||||||
|
return super<A>.bal
|
||||||
|
}
|
||||||
|
|
||||||
|
fun supBalB(): Int {
|
||||||
|
return super<B>.bal
|
||||||
|
}
|
||||||
|
|
||||||
|
fun supBarA(): Int {
|
||||||
|
return super<A>.bar
|
||||||
|
}
|
||||||
|
|
||||||
|
fun supBarB(): Int {
|
||||||
|
return super<B>.bar
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setBarA(value: Int) {
|
||||||
|
super<A>.bar = value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setBarB(value: Int) {
|
||||||
|
super<B>.bar = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val c = C()
|
||||||
|
|
||||||
|
if (c.bal != 1) return "c.bal != 1, it: ${c.bal}"
|
||||||
|
if (c.bar != 22) return "c.bar != 22, it: ${c.bar}"
|
||||||
|
if (c.realBar != 3) return "c.realBar != 3, it: ${c.realBar}"
|
||||||
|
|
||||||
|
c.bar = 50
|
||||||
|
if (c.bar != 90) return "c.bar != 90, it: ${c.bar}"
|
||||||
|
|
||||||
|
if (c.supBalA() != 5) return "c.supBalA() != 5, it: ${c.supBalA()}"
|
||||||
|
if (c.supBalB() != 42) return "c.supBalB() != 42, it: ${c.supBalB()}"
|
||||||
|
|
||||||
|
if (c.supBarA() != 3) return "c.supBarA() != 3, it: ${c.supBarA()}"
|
||||||
|
if (c.supBarB() != 1003) return "c.supBarB() != 1003, it: ${c.supBarB()}"
|
||||||
|
|
||||||
|
c.setBarA(239)
|
||||||
|
if (c.realBar != 239) return "c.realBar != 239, it: ${c.realBar}"
|
||||||
|
if (c.supBarA() != 239) return "c.supBarA() != 239, it: ${c.supBarA()}"
|
||||||
|
if (c.supBarB() != 1239) return "c.supBarB() != 1239, it: ${c.supBarB()}"
|
||||||
|
|
||||||
|
c.setBarB(239)
|
||||||
|
if (c.realBar != 1239) return "c.realBar != 1239, it: ${c.realBar}"
|
||||||
|
if (c.supBarA() != 1239) return "c.supBarA() != 1239, it: ${c.supBarA()}"
|
||||||
|
if (c.supBarB() != 2239) return "c.supBarB() != 2239, it: ${c.supBarB()}"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
open class A {
|
||||||
|
open val a = 2
|
||||||
|
get() {
|
||||||
|
return $a + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
override val a: Int = 5
|
||||||
|
get() {
|
||||||
|
return super.a + 10 * $a + 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a = A()
|
||||||
|
val b = B()
|
||||||
|
|
||||||
|
if (a.a != 3) return "a.a != 3, it: ${a.a}"
|
||||||
|
if (b.a != 153) return "b.a != 153, it: ${b.a}"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
open class A {
|
||||||
|
open var a = 1
|
||||||
|
fun getAInA(): Int = a
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
override var a = 2
|
||||||
|
|
||||||
|
fun getSuperA(): Int {
|
||||||
|
return super.a
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setSuperA(value: Int) {
|
||||||
|
super.a = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a = A()
|
||||||
|
val b = B()
|
||||||
|
if (a.getAInA() != 1) return "a.getAInA() != 1, it: ${a.getAInA()}"
|
||||||
|
if (b.getAInA() != 2) return "b.getAInA() != 2, it: ${b.getAInA()}"
|
||||||
|
|
||||||
|
if (b.getSuperA() != 1) return "b.getSuperA() != 1, it: ${b.getSuperA()}"
|
||||||
|
b.setSuperA(3)
|
||||||
|
if (b.getSuperA() != 3) return "b.getSuperA() != 3, it: ${b.getSuperA()}"
|
||||||
|
|
||||||
|
if (b.getAInA() != 2) return "b.getAInA() != 2 after b.setAInB(3), it: ${b.getAInA()}"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user