The output is
1, with no newline. The Any in class B[Any] and class C[Any] is a type parameter name that shadows the standard type scala.Any inside those class bodies. Renaming it to T preserves the program's meaning. Thus new B[Int] has an inherited m(Double) and its own m(Int); obj1.m(1) selects the latter and prints 1. The call with 2.3 can only use the inherited m(Double), which computes a sum without printing.For
new C[Any], the supplied type argument is the standard scala.Any, so the overloads are m(Double) and m(scala.Any). The more-specific Double alternative accepts 4 by numeric widening, and accepts 5.6 directly. Both return sums without printing. A computed result is not automatically screen output. This reasoning uses the Scala 2.11 overload conventions of Question 5(a); type erasure does not turn either class's generic-argument overload into an method overriding of m(Double).Programming language polymorphism permits one interface or piece of code to work with values of several types, while providing the behavior appropriate to those values. For example a routine that calls
play through a Player reference can use a Regular, Optimistic, or House object without knowing its concrete software class.Use programming language polymorphism when clients should depend on a common contract while concrete behavior varies, or when an algorithm is independent of the element type. It avoids duplicating client logic or repeatedly inspecting concrete runtime types, and supports extensions behind the same interface. A shared interface must still have meaningful behavioral guarantees: merely giving unrelated operations the same name does not establish that implementations can safely replace one another.
Two mechanisms are subtype polymorphism and parametric polymorphism.
With subtype polymorphism, a trait or abstract class declares an operation and concrete subclasses implement or override it. A
Player reference holding a House object invokes House.play through dynamic dispatch. The client is written against the common contract.With parametric polymorphism, a software class or generic method has a type parameter, such as
List[T] or def identity[T](x: T): T = x. The same definition works for many supplied type arguments, with static relationships between input and output types. Method overloading is another mechanism, usually called ad hoc polymorphism: alternatives share a name but are selected from their parameter signatures at compile time.Each The Scala assignment
play call should make at most one hit and return true exactly when it did so; the supplied while loop invokes it again to decide whether another hit is needed. Add these accessors inside Player:def cards: List[Int] = _cards
def cards_=(cs: List[Int]): Unit = { _cards = cs }
def visibleValue: Int = _visibleValue
def visibleValue_=(v: Int): Unit = { _visibleValue = v }temp.cards = cs calls the setter, and visibleValue += cards.head uses the getter followed by the setter. The list getter exposes an immutable list value; updating the player's field still goes through the setter. The supplied initialization and hit maintain the hidden card at the last list position and visibleValue == cards.init.sum for each nonempty dealt hand.The concrete software classes implement the supplied strategies literally:
class Regular extends Player {
def play(visibleCards: List[Int]): Boolean = {
require(visibleCards.length == 1)
val total = value
if (total < 21 && total <= 21 - visibleCards.head) {
hit
true
} else false
}
}
class Optimistic extends Player {
def play(visibleCards: List[Int]): Boolean = {
if (value != 21) {
hit
true
} else false
}
}
class House extends Player {
def play(visibleCards: List[Int]): Boolean = {
val total = value
if (total < 21 && visibleCards.forall(v => total <= 21 - v)) {
hit
true
} else false
}
}House receives all other players' final visible totals, whereas a non-house player receives the singleton containing the house's first visible card. The universal test implements “for each other player,” including the vacuously true case of no other players. Subtype polymorphism gives the common player list a Player interface, and dynamic dispatch chooses the appropriate play implementation.These are the literal missing methods, but the printed specification does not guarantee a terminating game. An optimistic player with total who draws reaches ; every further positive card keeps the total above , so
value != 21 remains true. The claim that only finitely many further cards are requested is therefore inconsistent with the optimistic strategy on such executions, in the intended arithmetic model without overflow. If the intended rule is “stop on reaching or exceeding 21,” the necessary correction is to replace its test by value < 21; that changes the printed strategy and is not silently made here.There is a second printed mismatch:
nextInt(10) yields , so 1 + nextInt(10) yields , not . Preserve the supplied hit when filling its missing pieces; generating every value from through would require an explicit change to nextInt(11) in both dealing and hitting.[ref]https://www.scala-lang.org/api/2.11.12/scala/util/Random.html#nextInt(n:Int):Int. Scala 2.11.12 Random.nextInt, upper bound is exclusive
No winner-computation code is requested; the supplied loop only deals and requests cards. Articles by others on the same topic
There are currently no matching articles.