Scala Generics与案例类扩展密封特性

时间:2016-09-29 15:13:28

标签: scala

以下代码无法编译,我不明白为什么不

的原因
class FruitProcessor[T <: Fruit] {
  def process(fruit: T) = {
    // Do something with fruit
  }
}

class FruitBlender[T <: Fruit] {
  val fruitProcessor = new FruitProcessor[T]

  def blend(fruit: T) = {
    fruit match {
      case b: Banana => fruitProcessor.process(b)
      case a: Apple => fruitProcessor.process(a)
    }
  }
}


sealed trait Fruit
case class Banana(id: String) extends Fruit
case class Apple(id: String) extends Fruit

编译错误符合&#34;找到香蕉,需要T&#34;

我在这里做错了什么?

2 个答案:

答案 0 :(得分:3)

process方法需要类型为T的参数,但您传递的值为Banana。编译器不够聪明,无法确定调用T的代码路径中Banana总是fruitProcessor.process(b)。实际上你根本不需要那个匹配表达式。在这种情况下,方法T中的blendT想要的process相同。所以你可以拨打fruitProcessor.process(fruit)

答案 1 :(得分:1)

说出你的所作所为: 您使用FruitProcessor的子类T参数化Fruitprocess T。 然后,您使用FoodBlender的{​​{1}}子类T进行参数化,其FruitFoodProcessor[T]process T process T }。

由于您只能[S <: Fruit] Fruit而非T,即只有您的子类型Fruit Banana的特定实例,其中参数化参数化使用,而不是所有Apples,这不适用于特定类型TFruitBlenderclass Pear extends Fruit上的blend例如可以是def blend(fruit: Pear),在这种情况下,Apple的签名将是Banana,当然如果不兼容import android.content.Context; import android.graphics.PixelFormat; import android.graphics.Point; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import com.sleepycoat.tapxicon.utils.ScreenUtils; import java.security.InvalidAlgorithmParameterException; import static android.view.MotionEvent.ACTION_OUTSIDE; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN; import static android.view.WindowManager.LayoutParams.TYPE_PHONE; /** * Created by egslava on 24/08/16. * Unfortunately, Android system is not supported (or I could find how) managing keyboard in windows * (not activities) that are always on top. So we need to manage keyboard manually. */ public class TopScreenDrawerLogic { private static final String TAG = "TopScreenDrawerLogic"; final Keyboarder keyboarder; // private final View fakeFocus; View visibleView; DrawerView drawer; ScrollerLogic scroller; private final ScreenUtils utils; private final WindowManager wm; public static final int COMMON_WINDOW_FLAGS = FLAG_LAYOUT_NO_LIMITS | // for fast "resizing". Window can be moved out of screen FLAG_NOT_TOUCH_MODAL | // other windows (on the background, that our window is not overlapped) can intercept touch events FLAG_LAYOUT_IN_SCREEN; // need for right positioning (getting into account status bar) // when FLAG_LAYOUT_IN_SCREEN is set getHeight() will return value - navigation bar height public static final int BACKGROUND_WINDOW_FLAGS = COMMON_WINDOW_FLAGS | FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM; // "back" and other hardware buttons will go throw window public static final int FOREGROUND_WINDOW_FLAGS = COMMON_WINDOW_FLAGS | // FLAG_LOCAL_FOCUS_MODE | // FLAG_NOT_TOUCHABLE | // if we want go clicks throw the window FLAG_WATCH_OUTSIDE_TOUCH; // need to know when user touched outside of window to "unfocus" private final InputMethodManager imm; public static WindowManager.LayoutParams createLayout() { return new WindowManager.LayoutParams( MATCH_PARENT, MATCH_PARENT, TYPE_PHONE, FOREGROUND_WINDOW_FLAGS, PixelFormat.TRANSLUCENT); } ////////////////////////////////////////////////////// // mrtndat add 9/9 ////////////////////////////////////////////////////// public static WindowManager.LayoutParams createLayout(Context context) { // int w Point navBarSize = ScreenUtils.getNavigationBarSize(context); Point screenSize = ScreenUtils.getRealScreenSize(context); int maxHeight = navBarSize != null ? (screenSize.y - navBarSize.y) : screenSize.y; WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT); // params.gravity = Gravity.TOP; // params.x = 0; // int diff = 0; // if (navBarSize != null) { // diff = maxHeight - navBarSize.y; // } // if (navBarSize != null) { // params.y = -navBarSize.y+144; // } return params; } ////////////////////////////////////////////////////// // mrtndat end 9/9 ////////////////////////////////////////////////////// public TopScreenDrawerLogic(DrawerView drawer, View visibleView) { this.visibleView = visibleView; this.drawer = drawer; scroller = new ScrollerLogic(drawer); keyboarder = new Keyboarder(drawer); utils = new ScreenUtils(drawer.getContext()); wm = drawer.windowManager; imm = (InputMethodManager) drawer.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); // this.fakeFocus = fakeFocus; } public int minY() { return 0; } public int maxY() { int[] location = new int[2]; visibleView.getLocationInWindow(location); int visibleViewTop = location[1]; ViewGroup.MarginLayoutParams margins = (ViewGroup.MarginLayoutParams) visibleView.getLayoutParams(); int visibleViewBottom = visibleViewTop + visibleView.getHeight() + margins.bottomMargin; //just a bit margin; return utils.getDisplayHeight() - visibleViewBottom;// - navBarHeight; } private int minY(int value) { return Math.max(value, minY()); } private int maxY(int value) { return Math.min(maxY(), value); } ; public int boundY(int y) { return maxY(minY(y)); } // difference between nearest correct Y value and given public int yCorrection(int y) { return y - boundY(y); } public int shiftDrawer(int dy) { return shiftDrawer(dy, false); } /** * shifts drawer and returns new y coordinate */ public int shiftDrawer(int dy, boolean animated) { WindowManager.LayoutParams params = drawer.getLayoutParams(); WindowManager wm = drawer.windowManager; // params.y = params.y + dy; if (dy > 1500) { new Throwable().printStackTrace(); } final int newY = drawer.logic.boundY(params.y + dy); if (animated) { new TranslateDrawerAnim(drawer, boundY(drawer.getLayoutParams().y + (int) dy)/* target layout height */, 250).execute(); } else { params.y = newY; wm.updateViewLayout(drawer, params); } return params.y; } public int shiftDrawerByScreenPercent(float dy, boolean animated) { return shiftDrawer((int) (utils.getDisplayHeight() / 100.0f * dy), animated); } public static final int STATE_UNDEFINED = 0; public static final int STATE_FOREGROUND = 1; public static final int STATE_BACKGROUND = 2; public static final int INITIAL_STATE = STATE_FOREGROUND; public int state = INITIAL_STATE; public void resetState(View focusedView) { if (INITIAL_STATE == STATE_BACKGROUND) { makeBackground(); } else if (INITIAL_STATE == STATE_FOREGROUND) { makeForeground(); } else throw new RuntimeException(new InvalidAlgorithmParameterException("Strange state")); } public void makeBackground() { new Throwable().printStackTrace(); Log.d(TAG, "makeBackground()" + ", previous state = " + stateToString(state)); if (state == STATE_BACKGROUND) return; state = STATE_BACKGROUND; imm.hideSoftInputFromWindow(drawer.getWindowToken(), 0); WindowManager.LayoutParams params = drawer.getLayoutParams(); WindowManager wm = drawer.windowManager; params.softInputMode = SOFT_INPUT_STATE_ALWAYS_HIDDEN; params.flags = BACKGROUND_WINDOW_FLAGS; wm.updateViewLayout(drawer, params); // final View focus = drawer.findFocus(); // if (focus != null) focus.postDelayed(new Runnable() { // @Override // public void run() { // imm.hideSoftInputFromWindow(drawer.getWindowToken(), 0, new ResultReceiver(new Handler(new Handler.Callback() { // @Override // public boolean handleMessage(Message message) { // fakeFocus.requestFocus(); // keyboarder.applyPos(); // return true; // } // }))); // } // }, 250); } public String stateToString(int state) { switch (state) { case STATE_BACKGROUND: return "background"; case STATE_FOREGROUND: return "foreground"; default: throw new RuntimeException("Invalid state"); } } public void makeForeground() { new Throwable().printStackTrace(); Log.d(TAG, "makeForeground()" + ", previous state = " + stateToString(state)); if (state == STATE_FOREGROUND) return; state = STATE_FOREGROUND; WindowManager.LayoutParams params = drawer.getLayoutParams(); WindowManager wm = drawer.windowManager; params.flags = FOREGROUND_WINDOW_FLAGS; // params.softInputMode = SOFT_INPUT_STATE_UNCHANGED; params.softInputMode = SOFT_INPUT_STATE_HIDDEN; // params.softInputMode = SOFT_INPUT_STATE_VISIBLE; wm.updateViewLayout(drawer, params); // request focus on focused element. Why? The reason: // 1. when window is in background state it can't be focused. // 2. when window is in foreground state some time it focuses last focused element // 3. when this happens Android shows keyboard but DOESN'T call onFocusChanged // 4. #Keyboarder class can't process this case correctly and move drawer on keyboard level // final View focus = drawer.findFocus(); // if (focus != null)focus.postDelayed(new Runnable() { // @Override // public void run() { // focus.requestFocus(); // } // }, 250); } public void dispatchTouchEvent(MotionEvent e) { Log.d(TAG, "dispatchTouchEvent() called with: " + "e = [" + e + "]"); switch (e.getAction()) { case ACTION_OUTSIDE: makeBackground(); break; default: makeForeground(); break; } } public boolean delegateOnTouch(MotionEvent e) { Log.d(TAG, "delegateOnTouch() called with: " + "e = [" + e + "]"); keyboarder.delegateOnTouch(e); return scroller.delegateOnTouch(e); } // need to process keyboard by ourselves public void delegateOnInputClick(final View v) { keyboarder.delegateOnInputClick(v); } public void delegateOnInputFocus(final View v, final boolean b) { keyboarder.delegateOnInputFocus(v, b); } public boolean delegateOnInterceptTouch(MotionEvent e) { return scroller.delegateOnInterceptTouch(e); } public void callWhenEnterIsPressed() { } public void callWhenKeypressed() { // for backpressing } public void callWhenKeyboardIsShown() { } public void delegateOnKeyPreIme(int keyCode, KeyEvent event) { keyboarder.delegateOnKeyPreIme(keyCode, event); } } s或<?php $selvals = array("Manhattan", "Bronx", "Brooklyn"); ?> <label class="checkbox-inline"><input type="checkbox" <?php if(in_array("Manhattan",$selvals)){ echo 'checked="checked"';}?> name="manhattan" value="Manhattan" >Manhattan</label> <label class="checkbox-inline"><input type="checkbox" <?php if(in_array("Bronx",$selvals)){ echo 'checked="checked"';}?> name="bronx" value="Bronx" >Bronx</label> <label class="checkbox-inline"><input type="checkbox" <?php if(in_array("Brooklyn",$selvals)){ echo 'checked="checked"';}?> name="brooklyn" value="Brooklyn" >Brooklyn</label> <label class="checkbox-inline"><input type="checkbox" <?php if(in_array("Queens",$selvals)){ echo 'checked="checked"';}?> name="queen" value="Queens" >Queens</label> <label class="checkbox-inline"><input type="checkbox" <?php if(in_array("Staten Island",$selvals)){ echo 'checked="checked"';}?> name="staten" value="Staten Island" >Staten Island</label> s。